【问题标题】:Having issues Mocking an Iterator Class within Mockito在 Mockito 中模拟迭代器类时遇到问题
【发布时间】:2019-07-11 19:32:44
【问题描述】:

我正在尝试模拟一个 SOAP 拦截器类,其中一个类方法返回一个 Iterator 对象。然而,在仔细检查语法后,迭代器并没有被真正的迭代器替换,Mockito 继续运行没有真正迭代器的方法。

我尝试使用各种 mockito 方法(doReturn、when...thenReturn)来模拟拦截器的返回值,但这些方法都没有奏效。我不确定我在嘲笑中的错误在哪里。

这是我在测试类中模拟当前对象的方式:

@Mock private WebServiceTemplate template;
@Mock private SoapInterceptor interceptor;
@Mock private Iterator<Attachment> iterator;

    @Test
    public void testGetDocsSoapClient() {
        @SuppressWarnings("unchecked")
        Iterator<Attachment> realIterator = new ArrayListIterator();
        ObjectFactory realFactory = new ObjectFactory();

        assertFalse(realIterator.hasNext());

        doReturn(realFactory.createAwsGetDocsRequest(createMockAwsGetDocsReq()))
            .when(factory).createAwsGetDocsRequest(any (AwsGetDocsRequest.class));
        doReturn(realFactory.createAwsGetDocsResponse(createAwsGetDocsResponse()))
            .when(template).marshalSendAndReceive(any(Object.class), any(SoapActionCallback.class));
        doReturn(realIterator)
            .when(interceptor).getSoapAttachments();

这是在真实类中调用方法的方式。

Iterator<Attachment> soapAttachments = attachmentInterceptor.getSoapAttachments();
ImageListDVO imgList = convertToImageList(soapAttachments);

...我的测试用例在这个私有方法的最后一行失败了。

private ImageListDVO convertToImageList(Iterator<Attachment> attachments) {
        ImageListDVO imgList = new ImageListDVO();

        while(attachments.hasNext()) {

我应该正确地模拟对象,但我得到一个 NullPointerException,这表明该对象没有被正确地模拟或注入。

【问题讨论】:

  • 为什么要模拟一个迭代器?使用Arrays.asList(/* whatever elements */).iterator() 创建一个真正的迭代器。
  • @AndyTurner 嗯,即使我这样做,我创建的真正迭代器也没有正确注入到模拟对象中。我在测试用例中做了类似的事情

标签: java iterator mockito


【解决方案1】:

我认为您使用了错误的语法。如果我理解正确,您需要模拟SoapInterceptor,它有一个方法getSoapAttachments()

为此,您需要将代码更改为以下内容:

    @InjectMocks
    // the class under test should be put here

    @Mock
    SoapInterceptor attachmentInterceptor;

    @Test
    public void testGetDocsSoapClient() {

       // this is either a real interceptor or a mocked version of it
       Iterator<Attachment> iterator = ... ;
       when(attachmentInterceptor.getSoapAttachments()).thenReturn(iterator);
    }

do 方法通常用于模拟 void 方法。

你还写了你已经尝试过了,所以很可能你没有正确初始化 Mockito。


确保使用正确的 Runner/Extension/Rule 或其他任何东西(例如 MockitoAnnotations.initMocks(testClass))。您可能使用的 JUnit 版本之间存在某些差异。 (如果您仍然需要帮助,请提供您正在使用的 JUnit 和 Mockito Verison)。

(见https://static.javadoc.io/org.mockito/mockito-core/2.28.2/org/mockito/Mockito.html#9


另一种未注入事物的可能性可能是您的类的结构以 mockito 无法处理的方式。

根据您的测试用例,我假设您使用了字段注入,因此 @Mock 注释字段应该与您在测试类中的 private 字段具有相同的名称。所以我又一次不确定是哪一个,因为你没有提供名字。

除非您手动提供 Mocks,否则您正在使用的此类应该有一个适当的 @InjectMocks 注释。 (但在这种情况下,您可能不会使用 @Mock 注释)。



编辑:
您的问题的另一种解释可能是您正在尝试测试 SoapInterceptor 本身的方法,并且您想用其他方法替换返回 Iterator 的方法。

在这种情况下,您应该考虑创建 Spy,而您的代码应该如下所示:

    @Test
    public void testGetDocsSoapClient() {

        SoapInterceptor interceptor = new SoapInterceptor();
        SoapInterceptor spy = Mockito.spy(interceptor);

        when(spy.getSoapAttachments()).thenReturn(iterator);

        ...
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2023-02-13
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    相关资源
    最近更新 更多