简体   繁体   English

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

[英]Having issues Mocking an Iterator Class within Mockito

I'm trying to mock a SOAP Interceptor class, where one of the class methods returns an Iterator object. 我正在尝试模拟SOAP Interceptor类,其中一个类方法返回一个Iterator对象。 However, after double checking the syntax, the iterator is not replaced with the real iterator, and Mockito continues to run the method without the real iterator. 但是,在仔细检查语法之后,不会用真实的迭代器替换迭代器,并且Mockito会在没有真实的迭代器的情况下继续运行该方法。

I've tried mocking the return value of the interceptor using the various mockito methods (doReturn, when... thenReturn) and neither of the methods have worked. 我尝试使用各种模拟方法(doReturn,何时... thenReturn)来模拟拦截器的返回值,但是这两种方法均无效。 I'm not sure where my error is in my mocking. 我不确定我的错误在哪里。

Here is how I mock the current object within my test class: 这是我在测试类中模拟当前对象的方式:

@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();

Here is how the method is called within the real class. 这是在实类中调用该方法的方式。

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

... and my test case fails at the last line of this private method. ...并且我的测试用例在此私有方法的最后一行失败。

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

        while(attachments.hasNext()) {

I should be mocking the object correctly, but I am getting a NullPointerException, which indicates that the object is not being mocked nor injected correctly. 我应该正确地模拟对象,但是我得到了NullPointerException,它指示对象没有被模拟或正确注入。

I think you are using the wrong syntax. 我认为您使用的是错误的语法。 If I understand correctly you need to mock the SoapInterceptor which has a method getSoapAttachments() 如果我理解正确的话,你需要模拟SoapInterceptor其中有一个方法getSoapAttachments()

To do that you need to change your code to something like this: 为此,您需要将代码更改为以下内容:

    @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);
    }

The do methods are normally used when you want to mock void methods. 当您要模拟void方法时,通常使用do方法。

You also wrote you already tried this, so its likely that you do not initialize Mockito correctly. 您还写了您已经尝试过的方法,因此很可能您没有正确初始化Mockito。


Make sure you use the proper Runner / Extension / Rule or whatever else there is (like MockitoAnnotations.initMocks(testClass)). 确保使用正确的Runner / Extension / Rule或其他任何方式(例如MockitoAnnotations.initMocks(testClass))。 There are certain differences between the JUnit version you might be using. 您可能使用的JUnit版本之间存在某些差异。 (If you still need help with that provide the JUnit & Mockito Verison you are using). (如果您仍然需要帮助,请提供正在使用的JUnit&Mockito Verison)。

(see https://static.javadoc.io/org.mockito/mockito-core/2.28.2/org/mockito/Mockito.html#9 ) (请参阅https://static.javadoc.io/org.mockito/mockito-core/2.28.2/org/mockito/Mockito.html#9


Another possibility that things are not injected might be that your class is structured in a way mockito can`t handle. 没有注入的另一种可能性可能是您的类以无法处理的方式构造。

From your test case I would assume you used field injection, so the @Mock annotated field should have the same name as the private field you have in your Test Class. 从您的测试用例中,我假设您使用了字段注入,因此带@Mock注释的字段应与测试类中的private字段具有相同的名称。 So once again I am not sure which one that is as you didn`t provide the name. 因此,我不确定您提供的名称是哪一个。

There should be a proper @InjectMocks annotation for this class you are using, unless you provide the Mocks manually. 除非您手动提供Mocks,否则对于正在使用的此类,应该有一个正确的@InjectMocks批注。 (But in this case you probably woudn`t use the @Mock annotation). (但是在这种情况下,您可能不会使用@Mock注释)。



Edit: 编辑:
Another interpretation of you question could be that you are the trying to test a method of the SoapInterceptor itself and you want to replace the method that returns the Iterator with something else. 对您问题的另一种解释可能是您正在尝试测试SoapInterceptor本身的方法,并且想要用其他方式替换返回Iterator的方法。

In that case you should look into the creation of a Spy instead and your code should look like this: 在这种情况下,您应该研究Spy的创建,并且您的代码应如下所示:

    @Test
    public void testGetDocsSoapClient() {

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

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

        ...
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM