Reputation: 10401
I'm building test cases using Powermock for a Jersey web service and I'm attempting to mock the database function calls, specifically for the PUT and POST calls. However, I'm having issues getting this to work.
Here is what one of the web service calls looks like:
@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
}
}
And what my test case currently looks like:
@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);
}
}
When run this is giving me an AssertionError saying:
Unexpected method call 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
After doing a little more digging I found that the reason is most likely related to how PowerMock is comparing the String arrays. So I've also tried going with a more generic approach, since the function returns void anyway, by using EasyMock.anyString()
and EasyMock.isA(String[].class)
in place of my two arguments but that results in a NullPointerException instead. Here are the first few lines of that stacktrace:
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)
How do I go about correctly mocking this private void method to avoid the database calls during my testing?
Upvotes: 1
Views: 202
Reputation: 10401
After digging through this test and the docs a few times I found that the expectPrivate
call was not finding my method. So here is how I found I could specify the function:
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;
}
});
This also allowed me to do a compare with the array that the function called like I originally wanted to while defining the function by using the generic types.
Upvotes: 1