当前位置: 首页 > 知识库问答 >
问题:

使用when(methodX).ThenReturn(resultY),是否调用了methodX?

暴才俊
2023-03-14

我有一些困难嘲弄一些单元测试的必要依赖。我怀疑我没有正确理解如何使用Mockito when().ThenReturn()。

下面是我要测试的服务的代码部分(希望是相关的):

@Singleton
public class AppointmentService {
    private DataConnector connector;

    @Inject
    public AppointmentService(DataConnector connector) {
        this.connector = connector;
    }

    public Appointment getAppointment(UriInfo uriInfo, String id) {
        HttpResponse response = connector.getAppointment(id);
        return validateResponse(response, uriInfo);
    }

    protected Appointment validateResponse(HttpResponse response, UriInfo uriInfo) {
        try {
            AppointmentWrapper appointmentWrapper = JacksonJsonUtility.readValue(response.getInputStream(), AppointmentWrapper.class);
            if(appointmentWrapper.getAppointment()!=null) {
                return appointmentConverterHelper(appointmentWrapper.getAppointment(), uriInfo.getPath());
            }
        } catch(IOException e) {
            throw new ResponseParsingException("IOException: " + e.getMessage());
        }
    }

    protected Appointment appointmentConverterHelper(ExternalAppointmentModel appointmentDto, String uriPath) {
        if (appointmentDto == null) {
            throw new BrickworkQueryException("Got an invalid appointment object from Brickwork!");
        }

        Customer customer = new Customer(new Name(appointmentDto.getCustomer().getName()),
            appointmentDto.getCustomer().getEmail(),
            String.valueOf(appointmentDto.getCustomer().getCode()));

        return new Appointment(
            appointmentDto.getId(),
            customer);
    }

}

我的理解是,这个方法的单元测试应该如下所示:

public class AppointmentServiceTest {

    private UriInfo mockUriInfo;
    private HttpResponse mockHttpResponse;

    @Mock
    private DataConnector mockDataConnector;

    @InjectMocks
    private AppointmentService appointmentService;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mockUriInfo();
        mockHttpResponse();
    }

    private void mockUriInfo() {
        mockUriInfo = mock(UriInfo.class);
        when(mockUriInfo.getRequestUri()).thenReturn(
            URI.create("http://localhost:8080"));
    }

    private void mockHttpResponse() {
        mockHttpResponse = mock(HttpResponse.class);
        when(mockHttpResponse.getInputStream()).thenReturn(
            IOUtils.toInputStream("{\"appointment\":{}}"));
    }

    @Test
    public void testGetAppointment() throws Exception {
        when(mockDataConnector.getAppointmentById(Mockito.anyString())).
            thenReturn(mockHttpResponse);
        when(appointmentService.validateResponse(Mockito.any(HttpResponse.class), Mockito.any(UriInfo.class))).
            thenReturn(new Appointment());
        appointmentService.getAppointment(mockUriInfo, "12345");
        verify(mockDataConnector).getAppointment(Mockito.anyString());
    }
}

当我运行测试时,在尝试调用appointmentTo.getCustomer()时,在appointmentConverterHelper方法中得到一个NullPointerException(可以理解为空)。由于代码现在正在运行,在我看来,我将需要在我的mockHttpResponse中返回一个包含完全有效约会的InputStream。既然我有when(appointmentService.validateresponse(mockHttpResponse,mockUriInfo)).thenreturn(new Appointment());难道不应该调用validateresponse并返回空的Appointment对象而不是实际运行validateresponse吗?

这里是AppointmentServiceTest的exception-line 140的堆栈跟踪是上面的when语句,以供参考。AppointmentsService的第176行是JacksonJsonUtility.ReadValue(response.GetInputStream(),appointmentWrapper.Class);ValidateResponse方法开头的行:

java.lang.NullPointerException
    at com.nike.appointmentservice.service.AppointmentsService.validatedResponse(AppointmentsService.java:176)
    at com.nike.appointmentservice.service.AppointmentsServiceTest.testGetAppointmentById(AppointmentsServiceTest.java:140)
    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:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)```

共有2个答案

闾丘永春
2023-03-14

基于这篇文章,我认为监视AppointmentService是允许我模拟validateresponse调用的方法。下面是我的测试现在的样子:

public class AppointmentServiceTest {

    private UriInfo mockUriInfo;
    private HttpResponse mockHttpResponse;

    @Mock
    private DataConnector mockDataConnector;

    @Spy
    private AppointmentsService appointmentsServiceSpy;

    @InjectMocks
    private AppointmentService appointmentService;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        appointmentsServiceSpy = spy(appointmentsService);
        mockUriInfo();
        mockHttpResponse();
    }

    private void mockUriInfo() {
        mockUriInfo = mock(UriInfo.class);
        when(mockUriInfo.getRequestUri()).thenReturn(
            URI.create("http://localhost:8080"));
    }

    private void mockHttpResponse() {
        mockHttpResponse = mock(HttpResponse.class);
        when(mockHttpResponse.getInputStream()).thenReturn(
            IOUtils.toInputStream("{\"appointment\":{}}"));
    }

    @Test
    public void testGetAppointment() throws Exception {
        when(mockDataConnector.getAppointmentById(Mockito.anyString())).
            thenReturn(mockHttpResponse);
        doReturn(new Appointment()).when(appointmentsServiceSpy).validateResponse(Mockito.any(HttpResponse.class), Mockito.any(UriInfo.class));
        appointmentServiceSpy.getAppointment(mockUriInfo, "12345");
        verify(mockDataConnector).getAppointmentById(Mockito.anyString());
    }
}

我仍然在实际的appointmentServicespy.getappointment调用中遇到一个异常,但我认为这是一个与如何使用间谍有关的单独问题。就原问题而言,使用带有doReturn().when()语句的spy可以解决使用when().thenReturn()语句时错误调用方法的问题。

郑佐
2023-03-14

我认为问题可能是when语句试图与特定实例匹配,但失败了。要开始使用Mockito单元测试,您应该将when语句中的特定值替换为表示“anything”的Mockito占位符。例如:

when(mockDataConnector.getAppointmentById(Mockito.anyString())).
  thenReturn(mockHttpResponse);

when(appointmentService.validateResponse(Mockito.any(HttpResponse.class), Mockito.any(UriInfo.class))).
        thenReturn(new Appointment());

当基本单元测试工作时,就可以添加更具体的单元测试。

更新

我现在注意到,您正在尝试测试appointmentService类,但同时也在模拟该类中的validateresponsehtml" target="_blank">方法。作为一个Mockito专家,我还不足以知道这是否完全不正确,但这不是我在单元测试中使用Mockito的方式。我正在测试的类根本没有被嘲弄,而是模拟它调用的类,以便模拟变量行为,并查看被测试类如何响应。

我认为您可能需要模拟JacksonJsonUtility类(powermock帮助处理静态类),并删除ValidateResponse方法上的模拟。您将需要构造JacksonJsonUtility.ReadValue方法的模拟响应,以便它包含AppointmentService类所需的所有内容。

 类似资料:
  • 我使用下面的命令进行了mockito-junit测试。变量serviceTask是接口的实例,称为serviceTask。我在申报中使用了@Mock 声明: 命令行: 堆栈跟踪: Java语言lang.NullPointerException在sun。反映NativeMethodAccessorImpl。sun上的invoke0(本机方法)。反映NativeMethodAccessorImpl。在

  • 我试图存根这个方法:QueryUtils.to顺序(排序,根,构建器)和我正在做 但它进入queryUtils方法体,它会说Sort为null,并抛出一个NPE。但是,当它是存根时,为什么需要进入方法体?我以前没有遇到过这个问题,我认为它不应该关心该方法的内部逻辑是什么。

  • 有一个类,并希望模拟/存根一个方法 测试; 在< code > when(the spy . merge list(any(list . class),any(HttpCookie.class))上出现异常< code > NullPointerException 。then return(fakeCookieList);。 日志显示两行: 显然,mergeList()是用空参数执行的,并在(Ht

  • 我在测试中使用@MockBean时使用Mockito.when(). thenBack()遇到了一些问题。 这是我的测试课: 其中getPayload()返回将使用Jackson转换为控制器对象的有效负载字符串。 这是我正在测试的控制器: 我现在收到Mockito的投诉。什么时候然后返回用法: 最后这里是我的KafkaPublisher: 我有两个问题: 如果我取出Mockito.when.the

  • 我有一个GWT应用程序,我从文本框中获取输入,检查正则表达式的值,如果匹配,然后我将该文本添加到表格中。当我为例如“你好”输入任何正确的输入时,它工作得非常好。 任何帮助都将不胜感激。

  • 问题内容: 如果返回错误,是否仍在调用? 问题答案: 不,延迟功能不会运行。 这是log.Fatal的描述: 致命等同于Print(),然后调用os.Exit(1)。 呼叫,其描述在这里: 退出使当前程序以给定的状态码退出。按照惯例,代码零表示成功,代码零表示错误。程序立即终止;延迟功能未运行。 示范 如果您确实需要在程序完成之前正确关闭资源或执行某些任务,请不要使用。