在Mockito中模拟迭代器类时遇到问题

时间:2019-07-11 19:32:44

标签: java iterator mockito

我正在尝试模拟SOAP Interceptor类,其中一种类方法返回Iterator对象。但是,在仔细检查语法之后,迭代器不会被真正的迭代器替换,并且Mockito会在没有真正的迭代器的情况下继续运行该方法。

我尝试使用各种模拟方法(doReturn,何时... 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()) {

我应该正确地模拟对象,但是我得到了一个N​​ullPointerException,它指示对象没有被正确模拟或注入。

1 个答案:

答案 0 :(得分:0)

我认为您使用的是错误的语法。如果我理解正确,则需要模拟具有方法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


另一个未注入的可能性是您的类以模仿无法处理的方式构造。

从您的测试用例中,我假设您使用了字段注入,因此@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);

        ...
    }