如何从 Mockito Junit 正确调用 super class 方法
How to call super class method correctly from Mockito Junit
我有一个基本处理程序
public class BaseHandler {
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = new JsonObject();
jsonObject.put("baseKey", "baseValue");
return jsonObject
}
}
还有一个子处理程序
public class ChildHandler extends BaseHandler {
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) super.extractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
}
我已经使用 Mockito 编写了 Junit 代码
@Test
public void extractInputTest() {
ChildHandler handler = spy(new ChildHandler());
RoutingContext rc = mock(RoutingContext.class);
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
doReturn(jsonObject).when((BaseHandler)handler).extractInput(eq(rc));
doReturn(optional).when(handler).populateFileObjects(rc);
Object o = handler.extractInput(rc);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}
我尝试将断点放在 ChildHandler class 的 extractInput 方法的第一行,但发现它从未被调用过。
模拟 super.method 调用的正确方法是什么?
有一种方法可以做到这一点,但它不是很干净,但它比用 Java 反射做同样肮脏的事情要好。您应该在子 class 的另一个方法中提取对 super 方法的调用,例如:
public class ChildHandler extends BaseHandler {
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) superExtractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
protected Object superExtractInput(RoutingContext rc){
super.extractInput(rc);
}
}
你的测试看起来像:
@Test
public void extractInputTest() {
ChildHandler handler = spy(new ChildHandler());
RoutingContext rc = mock(RoutingContext.class);
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
doReturn(jsonObject).when(handler).superExtractInput(eq(rc));
doReturn(optional).when(handler).populateFileObjects(rc);
Object o = handler.extractInput(rc);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}
最好favor composition over inheritance,避免在测试阶段出现此类问题。
classes 就像:
public class BaseHandler {
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = new JsonObject();
jsonObject.put("baseKey", "baseValue");
return jsonObject
}
}
public class ChildHandler{
private final BaseHandler baseHandler;
public ChildHandler(final BaseHandler baseHandler){
this.baseHandler = baseHandler;
}
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) baseHandler.extractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
}
而且测试会更清楚:
@InjectMocks
ChildHandler testObj;
@Mock
BaseHandler baseHandlerMock;
@Mock
RoutingContext routingContextMock;
@Test
public void extractInputTest() {
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
when(baseHandlerMock.extractInput(routingContextMock)).thenReturn(routingContextMock);
doReturn(optional).when(handler).populateFileObjects(routingContextMock);
Object o = handler.extractInput(routingContextMock);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}
我有一个基本处理程序
public class BaseHandler {
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = new JsonObject();
jsonObject.put("baseKey", "baseValue");
return jsonObject
}
}
还有一个子处理程序
public class ChildHandler extends BaseHandler {
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) super.extractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
}
我已经使用 Mockito 编写了 Junit 代码
@Test
public void extractInputTest() {
ChildHandler handler = spy(new ChildHandler());
RoutingContext rc = mock(RoutingContext.class);
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
doReturn(jsonObject).when((BaseHandler)handler).extractInput(eq(rc));
doReturn(optional).when(handler).populateFileObjects(rc);
Object o = handler.extractInput(rc);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}
我尝试将断点放在 ChildHandler class 的 extractInput 方法的第一行,但发现它从未被调用过。
模拟 super.method 调用的正确方法是什么?
有一种方法可以做到这一点,但它不是很干净,但它比用 Java 反射做同样肮脏的事情要好。您应该在子 class 的另一个方法中提取对 super 方法的调用,例如:
public class ChildHandler extends BaseHandler {
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) superExtractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
protected Object superExtractInput(RoutingContext rc){
super.extractInput(rc);
}
}
你的测试看起来像:
@Test
public void extractInputTest() {
ChildHandler handler = spy(new ChildHandler());
RoutingContext rc = mock(RoutingContext.class);
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
doReturn(jsonObject).when(handler).superExtractInput(eq(rc));
doReturn(optional).when(handler).populateFileObjects(rc);
Object o = handler.extractInput(rc);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}
最好favor composition over inheritance,避免在测试阶段出现此类问题。
classes 就像:
public class BaseHandler {
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = new JsonObject();
jsonObject.put("baseKey", "baseValue");
return jsonObject
}
}
public class ChildHandler{
private final BaseHandler baseHandler;
public ChildHandler(final BaseHandler baseHandler){
this.baseHandler = baseHandler;
}
@Override
protected Object extractInput(RoutingContext rc) {
JsonObject jsonObject = (JsonObject) baseHandler.extractInput(rc);
populateFileObjects(rc).ifPresent(jsonArray -> json.put("fileUploads", jsonArray));
return jsonObject
}
}
而且测试会更清楚:
@InjectMocks
ChildHandler testObj;
@Mock
BaseHandler baseHandlerMock;
@Mock
RoutingContext routingContextMock;
@Test
public void extractInputTest() {
JsonObject jsonObject = new JsonObject();
jsonObject.put("key", "value");
JsonArray jsonArray = new JsonArray();
JsonObject fileObject = new JsonObject();
fileObject.put("fileName", "name");
jsonArray.add(fileObject);
Optional<JsonArray> optional = Optional.of(jsonArray);
when(baseHandlerMock.extractInput(routingContextMock)).thenReturn(routingContextMock);
doReturn(optional).when(handler).populateFileObjects(routingContextMock);
Object o = handler.extractInput(routingContextMock);
Map<String, Object> map = ((JsonObject) o).getMap();
Assert.assertEquals("value", ((JsonObject)o).getString("key"));
Assert.assertEquals(2, map.size()); //Junit fails here
Assert.assertEquals(JsonArray.class, map.get("fileUploads").getClass());
Assert.assertEquals(fileObject, ((JsonArray)map.get("fileUploads")).getJsonObject(0));
}