我正在使用Powermock为Jersey Web服务构建测试用例,我正在尝试模拟数据库函数调用,特别是对于PUT和POST调用。但是,我在解决这个问题时遇到了问题。
以下是其中一个Web服务调用:
@Path("/v1.0.0")
public class WebService {
@POST
@Path("application")
@Consumes(MediaType.APPLICATION_JSON)
public Response createApplication(@QueryParam("callback") String callbackFunction, String body)
throws NamingException, SQLException, IllegalStateException, CacheException, UnknownHostException,
IOException {
String query = "exec spInsertApplication ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?";
String[] params = new String[16];
JSONObject json = (JSONObject) JSONValue.parse(body);
params[0] = json.get("name").toString();
params[4] = json.get("software").toString();
params[14] = json.get("customerid").toString();
//Null checks for other params
runUpdateQuery(query, params);
return generateResponse(callbackFunction, null);
}
private void runUpdateQuery(String query, String[] queryParameters) {
//Handles running DB query
}
}
我的测试用例目前是什么样的:
@RunWith(PowerMockRunner.class)
@PrepareForTest(WebService.class)
@PowerMockIgnore( {"javax.management.*"})
public class TestRestWebService {
@Test
public void test_createApplication_returns_http_success() throws Exception {
String query = "exec spInsertApplication ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?";
String[] params = new String[16];
params[0] = "test_app_name";
params[4] = "test_software";
params[14] = "23";
WebService tested = createPartialMockAndInvokeDefaultConstructor(WebService.class, "runUpdateQuery");
expectPrivate(tested, "runUpdateQuery", query, params).andAnswer(
new IAnswer<Void>() {
@Override
public Void answer() throws Throwable {
return null;
}
});
replay(tested);
String JSONString = "{\"name\":\"test_service_name\",\"software\":\"test_software\",\"customerid\":\"23\"}";
Response output = tested.createApplication("CALLBACK", JSONString);
verify(tested);
assertTrue(output.getStatus() == 200);
}
}
运行时,这给我一个AssertionError说:
意外的方法调用WebService.runUpdateQuery(“exec spInsertApplication?,?,?,?,?,?,?,?,?,?,?,?,?, ?,?,?“,[”test_service_name“,null,null,null,”test_software“, null,null,null,null,null,null,null,null,null,“23”,null]):
WebService.runUpdateQuery(“exec spInsertApplication?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?“,[”test_service_name“,null, null,null,“test_software”,null,null,null,null,null,null,null, null,null,“23”,null]):expected:1,actual:0
在进行了一些挖掘之后,我发现其原因很可能与PowerMock如何比较String数组有关。所以我也尝试使用更通用的方法,因为函数无论如何都返回void,使用EasyMock.anyString()
和EasyMock.isA(String[].class)
来代替我的两个参数,但这会导致NullPointerException。以下是该堆栈跟踪的前几行:
java.lang.NullPointerException
at java.lang.Class.isAssignableFrom(Native Method)
at org.powermock.reflect.internal.WhiteboxImpl.checkIfParameterTypesAreSame(WhiteboxImpl.java:2432)
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1934)
at org.powermock.reflect.internal.WhiteboxImpl.getBestMethodCandidate(WhiteboxImpl.java:1025)
at org.powermock.reflect.internal.WhiteboxImpl.findMethodOrThrowException(WhiteboxImpl.java:948)
如何在测试过程中正确模拟这个私有void方法以避免数据库调用?
答案 0 :(得分:1)
经过几次测试和文档后,我发现expectPrivate
调用没有找到我的方法。所以我发现我可以指定函数:
expectPrivate(tested, WebService.class.getDeclaredMethod("runUpdateQuery", String.class, String[].class),
EasyMock.anyString(), EasyMock.aryEq(params)).andAnswer(new IAnswer<Void>() {
@Override
public Void answer() throws Throwable {
return null;
}
});
这也允许我在使用泛型类型定义函数时,与我最初想要的函数进行比较。