如何使用whenNew方法模拟ArrayList类

时间:2018-03-12 06:55:07

标签: java unit-testing mockito powermock

我试图模仿arraylist来验证添加方法,但我收到了消息:

FAILED: testInit
Wanted but not invoked:
arrayList.add(<any>);
-> at AsyncRestTemplateAutoConfigurationTest.testInit(AsyncRestTemplateAutoConfigurationTest.java:95)
Actually, there were zero interactions with this mock.

我使用的测试类是:

@Test
    public void testInit() throws Exception {

        ArrayList<AsyncClientHttpRequestInterceptor> interceptors = Mockito.mock(ArrayList.class);

        PowerMockito.whenNew(ArrayList.class).withAnyArguments()
                .thenReturn(interceptors);

        Mockito.stub(interceptors.add(Mockito.any())).toReturn(true);
        asyncRestTemplateAutoConfiguration.init();

        Mockito.verify(interceptors).add(Mockito.any());
    }

实际测试的代码是:

List<AsyncClientHttpRequestInterceptor> interceptors = new ArrayList<>(interceptors);
    interceptors.add(new TracingAsyncRestTemplateInterceptor(tracer));

我已经用

声明了测试类
@RunWith(PowerMockRunner.class)
@PrepareForTest(AsyncRestTemplateAutoConfiguration.class)

AsyncRestTemplateAutoConfiguration是哪个类,我用来测试。谁能告诉我我失踪了什么?

2 个答案:

答案 0 :(得分:3)

您的单元测试应验证公共可观察行为 返回值与依赖项的通信(这不仅仅意味着仅测试{ {1}}方法)。

您的生产代码使用public来存储您的数据是实施细节您不想测试,因为它可能会在不更改单位一般行为的情况下进行更改,在哪种情况下,你的单位测试不应该失败。

答案 1 :(得分:3)

不要开始学习如何使用PowerMockito进行单元测试 - 它会给你不良习惯。

相反,请考虑仔细阅读documentation for Mockito,您将看到如何构建类以便进行更好的测试。

理想情况下,您的课程应该是这样的,您不需要PowerMockito来测试它们,您可以只依靠普通的Mockito。

如果您能够使用Mockito进行优雅而简单的测试,那么您将掌握单元测试的基本概念。

您可以从学习如何通过类的构造函数注入依赖项开始,这些构造函数可以与模拟的测试双重交换,从而可以验证哪些行为。

另一点需要注意的是,根据另一个答案,被测系统中的内部ArrayList是一个实现细节。除非被测系统的消费者能够访问ArrayList,比如暴露它的方法,否则编写测试没有多大意义。

如果内部ArrayList的状态从消费者的角度影响了某些内容,那么请尝试针对该内容进行测试,而不是针对内部属性。

祝你在单元测试中获得成功!