【问题标题】:Jmockit - Mocked methods returning interfacesJmockit - 模拟方法返回接口
【发布时间】:2014-09-16 09:33:37
【问题描述】:

我有以下设置:

public String loadFile(String uri) throws ClientProtocolException, IOException {
        StringBuilder resp = new StringBuilder();
        HttpClient client = HttpClientBuilder.create().build();
        HttpGet request = new HttpGet(uri);
        HttpResponse response = client.execute(request);
}

Testclass 如下所示:

@RunWith(JMockit.class)
public class FakeLoaderTest {

    FakeLoader loader = new FakeLoader(); //class under test

    @Test
    public void testLoadFile(   
        @Mocked @Cascading final HttpClientBuilder mockBuilder,
        @Capturing  final HttpClient mockClient
    ) throws IOException, URISyntaxException{

        new Expectations() {{
            HttpClientBuilder.create().build(); result =  mockClient;
            mockClient.execute(withAny(mockget)); result =  new IOException("test - test");
        }};

        loader.loadFile();
    }
}

这给了我“意外调用 ClosableHttpClient.execute - 预期是 HttpClient.execute”

HttpClientBuilder.create.build() 返回一个 ClosableHttpClient,它实现了 HttpClient。我认为@Capturing 负责模拟所有扩展相关类/接口的类?

这工作正常,正如预期的那样:

    @Mocked @Cascading final HttpClientBuilder mockBuilder,
    @Capturing  final **Closeable**HttpClient mockClient

但我想针对接口进行测试,因为我没有测试使用的 HttpClient 实现。 在这个测试中,我不在乎 apache 的某个人是否决定 ClosableHttpClient 被“ThinHttpCLient”成功作为默认实现,只要 apache 坚持使用 HttpClient 接口,我就不想改变这个测试用例。它是关于测试 IO 异常的内部处理(例如,他是否登录到正确的位置?他是否正确重试等)

如何使用 JMockit 和 JUnit 处理这个问题?

提前致谢,

比尔门

【问题讨论】:

    标签: java junit jmockit


    【解决方案1】:

    测试应该如下:

    @Test(expected = IOException.class)
    public void loadFile(
        @Cascading HttpClientBuilder mockBuilder, 
        @Mocked final CloseableHttpClient mockClient
    ) throws Exception
    {
        new NonStrictExpectations() {{
            mockClient.execute((HttpGet) any); result = new IOException("test");
        }};
    
        loader.loadFile("uri");
    }
    

    HttpClientBuilder#build()的返回类型CloseableHttpClient,这是一个包含常用方法实现的抽象类。 Apache 项目永远不能将此返回类型更改为其他类型,因为这将是一个破坏性的 API 更改,导致编译错误。

    此外,在这种情况下,@Capturing@Mocked 没有什么区别,因为使用 @Cascading HttpClientBuilder 意味着不会实例化任何实际的实现类。

    【讨论】:

    • @Cascading(我猜对了)意味着链式调用返回的对象也将被模拟,所以我把它放在 build().create() 的份上,但感谢指点没有必要。至于 CloseableHttpClient 不可更改的 API,我记得使用过诸如“new DefaultHttpClient()”之类的东西,它现在已被弃用,并已更改为使用的 HttpClientBuilder().build().create()。如果 apache 提供接口,我想尽可能使用它。你是说你>确定
    • @billdoor DefaultHttpClient extends CloseableHttpClient,这实际上是库的真正基本类型。我不知道为什么需要 Java 接口,但我想说HttpClient 应该是CloseableHttpClient 的抽象类。所以,是的,如果他们让 build() 方法返回任何其他内容,我会感到非常惊讶。
    猜你喜欢
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 2021-11-08
    相关资源
    最近更新 更多