简体   繁体   English

模拟专用void方法可提供AssertionError

[英]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. 我正在使用Powermock for Jersey Web服务构建测试用例,并且试图模拟数据库函数调用,特别是针对PUT和POST调用。 However, I'm having issues getting this to work. 但是,我在使它起作用时遇到了问题。

Here is what one of the web service calls looks like: 以下是其中一个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
    }
}

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: 运行时,这给了我一个AssertionError说:

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]):

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 WebService.runUpdateQuery(“ exec spInsertApplication?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,,”,“” test_service_name“,null,null,null ,“ test_software”,null,null,null,null,null,null,null,null,null,“ 23”,null]):预期:1,实际:0

After doing a little more digging I found that the reason is most likely related to how PowerMock is comparing the String arrays. 经过更多的挖掘之后,我发现原因很可能与PowerMock如何比较String数组有关。 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. 因此,我也尝试使用一种更通用的方法,因为该函数无论如何都通过使用EasyMock.anyString()EasyMock.isA(String[].class)来代替我的两个参数而返回void,但这会导致NullPointerException代替。 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? 如何正确模拟此私有void方法,以避免在测试期间进行数据库调用?

After digging through this test and the docs a few times I found that the expectPrivate call was not finding my method. expectPrivate了该测试和文档几次之后,我发现expectPrivate调用未找到我的方法。 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. 这也使我可以在使用泛型类型定义函数时与函数调用的数组进行比较,就像我最初想要的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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