简体   繁体   中英

Mocking private void method gives AssertionError

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM