【问题标题】:EasyMock is calling the real methodEasyMock 调用的是真实方法
【发布时间】:2015-05-15 15:00:24
【问题描述】:

我有这个测试用例:

TestClient

@RunWith(EasyMockRunner.class)
public class TestClient extends EasyMockSupport {

    @TestSubject
    private final IClient client = new Client();

    @Mock
    private HttpClient httpClient;

    @Mock
    private HttpUriRequest request;
    @Mock
    private HttpResponse response;

    @Test
    public void testExecute() throws ClientProtocolException, IOException {
        expect(httpClient.execute(request)).andReturn(response);
        replayAll();
        httpClient.execute(request);
        client.execute(request);
        verifyAll();
    }
}

客户

public class Client implements IClient {

    private final HttpClient httpClient;

    public Client() {
        httpClient = createDefaultClient();
    }

    private HttpClient createDefaultClient() {
        return HttpClientBuilder.create()
                .build();
    }

    @Override
    public HttpResponse execute(final HttpUriRequest request)
            throws IOException {
        return httpClient.execute(request);
    }

}

当我运行它时,我得到了这个错误:

Unexpected method call HttpUriRequest.getURI()

创建的通常不会调用这个方法。

为什么会出现此错误?为什么需要我为getURI 方法定义结果?

【问题讨论】:

    标签: java unit-testing easymock


    【解决方案1】:

    您必须从

    中删除 final
    private final HttpClient httpClient;
    

    否则 EasyMock 无法用自己的模拟实例覆盖您的 httpClient。当然最好还是直接使用依赖注入,但这与您的实际问题无关。

    可以reflection 用作workaround;但亲爱的我不......


    原答案:

    发布完整的堆栈跟踪以及Client 课程的相关部分将帮助我们与您一起调试。你提到:

    client.execute(request) 我做httpClient.execute(request)

    但是(至少在您发布的代码中)client 没有得到对模拟的httpClient 实例的引用。您的 Client 类是否可能构建它自己的 HttpClient 实例,并针对 that 而不是您的模拟发出请求?

    如果是这样,您的Client 应该遵循dependency injection 模式并在构造时传入HttpClient 实例,而不是在内部构造一个。

    另一种可能性是您的 Client.execute() 方法在某个时候调用了 request.getURI(),在这种情况下,您只需通过 expect() 调用 request.getURI()

    【讨论】:

    • 模拟的httpClient 将被EasyMock 注入(这就是我使用TestSubject 注释的原因)。我同意如果我们不了解框架,它是不可见的。
    • @user230137 请包含您的Client 代码,以便我们查看它在做什么。如果您在Client 中的任何位置调用new HttpClient(),即使EasyMock 正在注入,也会被使用。
    • 我添加了客户端代码。删除 final 时它可以工作,但也许有解决方案。
    • 即使我在Client.execute() 中调用request.getURI(),它也应该可以工作,因为它不会调用它,因为该方法被模拟了。
    • @user230137 是的,问题在于您的 final httpClient 实例变量。更新了答案。
    【解决方案2】:

    我怀疑client.execute(request) 方法内部有一个request.getURI() 语句(或深埋在被调用的方法中)。 Easy Mock 需要知道调用此方法时要给出的响应。

    【讨论】:

    • client.execute(request) 我做httpClient.execute(request)。为什么 EasyMock 需要知道 getURI 方法的响应?我创造了对方法的期望。这不是嘲讽的意义吗?
    • @user230137 如果您发布Client.execute() 的内容会有所帮助;否则我们只能推测。
    【解决方案3】:

    我怀疑问题出在httpClient.execute(request); 的调用上。尝试删除它。您已经通过expect(httpClient.execute(request)).andReturn(response); 设置了对httpClient 的期望。

    @Test
    public void testExecute() throws ClientProtocolException, IOException {
        expect(httpClient.execute(request)).andReturn(response);
        replayAll();
        client.execute(request);
        verifyAll();
    }
    

    【讨论】:

    • 不,不是那样。 EasyMock 未能注入我的模拟,因为该字段是最终的,但默默地失败了
    猜你喜欢
    • 2018-09-10
    • 1970-01-01
    • 2017-03-06
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多