在同一方法调用中捕获模拟和参数

时间:2018-08-17 21:03:53

标签: java spring unit-testing junit mockito

我有以下方法/类

public class SomeServiceImpl{

    @Value("${someUrl}")
    private String someUrl;

    @Autowired
    private RestClientUtil restClientUtil;

    @Autowired
    private ObjectMapper objectMapper;

    public Some getSomeData(String place,String date) throws Exception{

        String response = null;
        someUrl = someUrl+ "?location="+place+"+date=+"+date;
        try {
            response = restClientUtil.getHttpCall(null, null, someUrl, null);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("Some Data Api call failed ");
        }

        Some some = objectMapper.readValue(response,Some.class);

        return some;
    }
}

下面是我尝试使用Spring Boot Test Mockito框架编写的相应测试用例。

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(properties={"someUrl = http://www.some_url.com"})
public class SomeServiceImplTests {

    @Value("${someUrl}")
    private String someUrl;

    @MockBean
    private RestClientUtil mockRestClientUtil;

    @MockBean
    private ObjectMapper mockObjectMapper;

    @Autowired
    private SomeServiceImpl someServiceImpl;



    @Test
    public void testGetSomeData() throws Exception{
        String place = "NewYork";
        Date date = new Date();
        String response = "xyz";
        Some  some = new Some();
        String username=  null;
        String password=  null;
        Map<String,String> headerMap = null;

        ArgumentCaptor<String> userNameCaptor = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<String> passwordCaptor = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<String> urlCaptor = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<Map<String,String>> headerCaptor = ArgumentCaptor.forClass(Map.class);

        String capusername = userNameCaptor.capture();
        String cappassword = passwordCaptor.capture();
        String capurl = urlCaptor.capture();
        Map<String,String> capHeader = headerCaptor.capture();



        when(mockRestClientUtil.getHttpCall(capusername,cappassword,capurl,capHeader)).thenReturn(response);

        ArgumentCaptor<String> responseCaptor = ArgumentCaptor.forClass(String.class);
        String capresponse = responseCaptor.capture();
        when(mockObjectMapper.readValue(capresponse,eq(Some.class))).thenReturn(some);

        assertEquals(some,someServiceImpl.getSomeData(place,date.toString()));


        verify(mockRestClientUtil, times(1)).getHttpCall(capusername,cappassword,capurl,capHeader);
        verify(mockObjectMapper,times(1)).readValue(capresponse, eq(Some.class));




        assertEquals(response,capresponse);
        assertEquals(username,capusername);
        assertEquals(password,cappassword);
        assertEquals(someUrl+ "?location="+place+"+date=+"+date,urlCaptor.getValue());
        assertEquals(headerMap,capHeader);
    }
}

我无法捕获并验证httpcall方法的参数,因此无法验证整个getSomeData方法。

我目前面临以下异常。

Argument(s) are different! Wanted:
restClientUtil bean.getHttpCall(
    null,
    null,
    null,
    null
);
-> at com.x.x.service.impl.SomeServiceImplTests.testGetSomeData(SomeServiceImplTests.java:83)
Actual invocation has different arguments:
restClientUtil bean.getHttpCall(
    null,
    null,
    "http://www.some_url.com?location=NewYork+date=+Sat Aug 18 02:15:28 IST 2018",
    null
);
-> at com.x.x.service.impl.SomeServiceImpl.getSomeData(SomeServiceImpl.java:36)

    at com.x.x.service.impl.SomeServiceImplTests.testGetSomeData(SomeServiceImplTests.java:83)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

我尝试重新排序验证,捕获和断言语句,以尝试运气。

需要帮助。 谢谢

1 个答案:

答案 0 :(得分:2)

通常的方法是处理模拟,然后进行捕获验证,然后处理断言。

类似的东西(未经测试,并且不想使用与您一样多的参数):

@Test
public void testThing() {
    final String response = "Pong";
    final String arg = "Ping";

    doReturn(response).when(mockService).call(arg);

    serviceWhichCallsMockService.triggerPing();

    final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

    verify(mockService).call(captor.capture());

    final String receivedArg = captor.getValue();

    // Confirms 'triggerPing' passed 'Ping' to your 'mockService'
    assertEquals(arg, receivedArg);
}