【问题标题】:Mockito doReturn/when executes real method (without CGILIB)Mockito doReturn/when 执行真实方法(没有 CGILIB)
【发布时间】:2013-12-11 19:42:43
【问题描述】:

我做了很多 Mockito 间谍,只是在一个新项目中模仿我自己的工作示例。但这失败得很惨

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static org.mockito.Mockito.*;

public class SpyTest {
    HttpClient httpClient;
    private HttpResponse httpResponse;
    private StatusLine responseStatus;
    private HttpEntity responseEntity;

    @BeforeMethod
    public void setupClient() throws Exception {
        List spy = spy(new ArrayList());
        doReturn(true).when(spy).addAll(any(Collection.class)); // this works!

        DefaultHttpClient directClient = new DefaultHttpClient();
        httpClient = spy(directClient);
        httpResponse = mock(HttpResponse.class);
        responseStatus = mock(StatusLine.class);
        responseEntity = mock(HttpEntity.class);
        doReturn(responseStatus).when(httpResponse).getStatusLine();
        doReturn(responseEntity).when(httpResponse).getEntity();
        doReturn(httpResponse).when(httpClient).execute(any(HttpPost.class)); // failing here
    }

    @Test
    public void itShouldSetupTheSpy() throws Exception {
        doReturn(200).when(responseStatus).getStatusCode();
        doReturn("OK").when(responseStatus).getReasonPhrase();
        doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                OutputStream os = (OutputStream) invocation.getArguments()[0];
                os.write("{\"id\": 100}".getBytes());
                return null;
            }
        }).when(responseEntity).writeTo(any(OutputStream.class));
    }
}

但我有错误

java.lang.IllegalArgumentException:请求不能为空。 在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:801) 在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) 在 SpyTest.setupClient(SpyTest.java:37)

我相信我已经关注了the official advice!就像我的其他间谍一样。还有this answer!似乎不适用于我,因为从 maven 依赖树中可以看出我没有使用 CGLIB:

[信息] +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.3:compile [信息] | \- org.codehaus.jackson:jackson-core-asl:jar:1.9.3:compile [信息] +- org.testng:testng:jar:6.8:test [信息] | +- junit:junit:jar:4.10:test [信息] | | \- org.hamcrest:hamcrest-core:jar:1.1:test [信息] | +- org.beanshell:bsh:jar:2.0b4:test [信息] | +- com.beust:jcommander:jar:1.27:test [信息] | \- org.yaml:snakeyaml:jar:1.6:test [信息] +- org.mockito:mockito-all:jar:1.9.5:test [信息] +- com.newrelic:newrelic-api:jar:2.3.0:compile [信息] +- org.apache.httpcomponents:httpclient:jar:4.2.5:compile [信息] | +- org.apache.httpcomponents:httpcore:jar:4.2.4:compile [信息] | +- commons-logging:commons-logging:jar:1.1.1:compile [信息] | \- commons-codec:commons-codec:jar:1.6:compile [信息] \- org.apache.commons:commons-lang3:jar:3.1:compile

看起来 HttpClient 及其子类有问题。

【问题讨论】:

  • doReturn(httpResponse).when(httpClient).execute(any(HttpPost.class)); 将编辑帖子

标签: java mocking testng mockito stubbing


【解决方案1】:

executefinal method,而 Mockito 无法模拟最终方法(如 the section on spyingthe FAQ 中所述)。

为什么?因为在正常情况下您无法覆盖 final 方法,Java 采用捷径并将调用(对 final 方法)直接编译到实现,而不是在 Java's equivalent of a virtual method table 中查找它们。这意味着 Mockito 永远不会参与最终方法调用,因此无法拦截行为甚至接收存根/验证调用。

您可以切换到模拟并改用a raw HttpClient 吗?您可以模拟接口的任何方法,而不必担心可见性或最终方法问题。

【讨论】:

  • 是的,确实如此。我在看接口方法,忘记检查实现了。
猜你喜欢
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多