【问题标题】:mocking consecutive REST call模拟连续的 REST 调用
【发布时间】:2016-05-12 15:51:54
【问题描述】:

我有一个 service/dao 层。服务层方法调用 dao 的第一个方法,我从中获得响应并调用 dao 中的第二个方法,传递一些参数,包括来自第一个 dao 方法的响应的值。我尝试使用模拟,但它因空指针而失败。 伪代码如下:

Service{
serviceMethod(some_args){
response1 = dao.method1(some_args);
someItem = response1.get("someItem");

/* do some logic on someitem to create otherItem*/
request2.setArgs(someItem);
response2 = dao.method2(request2);
}
}

我试图模拟如下,但它不起作用。

@Test
        public void testPass(){
        mockResponse1 = new Response1();
        mockRequest2 = new MockRequest2();
        when(dao.method1(some_args)).thenReturn(mockResponse1)
        mockResponse1.setArgs(some_args);
        mockRequest2.setArgs(mockResponse1.getargs());
        mockResponse2 = new Response2();
        when(dao.method2(mockRequest2)).thenReturn(mockResponse2)
        service.serviceMethod(some_args)
        }

【问题讨论】:

  • 这是一个真正的java代码还是只是一个伪代码?我看到 mockResponse1 是一个实际实例,而 mockResponse2 也是一个实际实例。如果你调用这些模拟,我期待的是模拟(Response1.class)和模拟(Response2.class)。如果您实际上没有注意到这一点,那么这就是您的问题。
  • code is something like 如果不包含实际创建模拟的代码 (= dao) 并且还包括将模拟注入到服务等级。此外,mockRequest2 没有在您的测试代码中的任何地方定义
  • 更新了伪代码
  • 请贴出真实代码和NPE的stacktrace
  • 由于您显然无法提供MCVE,这将变成一场猜谜游戏。 NPE 可能是由于没有将dao 定义为mock(SomeDao.class) 并将此dao-mock 注入Service 以便在服务方法内部对dao 的调用。由于在测试执行期间我们不知道您的服务类中的 dao 是什么,因此它可能会调用真正的 dao 类,或者 dao 可能为 null 并导致 NPE,除了不遵守您定义的规则。

标签: java unit-testing spring-mvc mockito


【解决方案1】:

您可以使用ArgumentCaptor 来获取传递给dao.method2(...) 的值,然后对其进行断言。

例如,假设我有这个 DAO...

public interface DAO {
    Response method1(Request request);    
    Response method2(Request request);
}

还有这项服务……

public class Service {

    private DAO dao;

    public void setDao(DAO dao) {
        this.dao = dao;
    }

    public Response serviceMethod(Request someArgs) {
        Response response1 = dao.method1(someArgs);
        String someItem = response1.getTheResponse();
        Request request2 = new Request(someItem);
        return dao.method2(request2);
    }
}

对此服务的测试可能是...

import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class ServiceTest {

    @Mock
    private Request request;

    @Mock
    private Response response;

    @Mock
    private Response serviceResponse;

    @Mock
    private DAO dao;

    @InjectMocks
    private Service service;

    @Captor
    private ArgumentCaptor<Request> requestCaptor;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void shouldDoServiceMethod() {
        // Set up
        when(dao.method1(request)).thenReturn(response);
        when(response.getTheResponse()).thenReturn("[ARGUMENT]");
        when(dao.method2(any(Request.class))).thenReturn(serviceResponse);

        // Code under test
        Response actualResponse = service.serviceMethod(request);

        // Verification
        assertThat(actualResponse).isSameAs(serviceResponse);

        verify(dao).method2(requestCaptor.capture());

        Request actualSecondRequest = requestCaptor.getValue();

        assertThat(actualSecondRequest.getArgs()).isEqualTo("[ARGUMENT]");
    }
}

关键是……

verify(dao).method2(requestCaptor.capture());

这将验证 method2 是否被调用并捕获它被调用的值。

然后你得到价值......

Request actualSecondRequest = requestCaptor.getValue();

...然后您可以验证是否设置了相关信息...

assertThat(actualSecondRequest.getArgs()).isEqualTo("[ARGUMENT]");

希望这会有所帮助。


为了完整起见,这里是 RequestResponse...

public class Request {

    private String args;

    public Request(String args) {
        this.args = args;
    }

    public String getArgs() {
        return args;
    }
}

public class Response {

    private String theResponse;

    public Response(String theResponse) {
        this.theResponse = theResponse;
    }

    public String getTheResponse() {
        return theResponse;
    }
}

【讨论】:

    猜你喜欢
    • 2011-11-06
    • 2018-12-30
    • 2016-10-13
    • 2022-12-13
    • 2022-01-26
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多