How to return a new instance every time doReturn is called?

user991710 :

I have the following test case:

ClassPathResource resource = new ClassPathResource(...);
doReturn(resource.getInputStream()).when(someMock).getInputStream();

where I read some resource and return it in my test. This method is called with some uncertainty in an asynchronous, scheduled manner in the actual production code - hence I do not have complete control over how many times it is exactly called, although the returned data is always the same (or should be).

In other words, this can potentially cause a randomly failing test if the method is invoked and the stream is read more times than expected, since the stream has not (and cannot) be reset, and is already at EOF.

I explicitly do not wish to have this be invoked synchronously in the test context, and am using Awaitility.await() to test these kinds of scenarios, so unfortunately that is not an option for me.

Now, the 'dumb' way to potentially fix this is something like the following:

doReturn(resource.getInputStream()).doReturn(resource.getInputStream()).<...>.when(someMock).getInputStream();

But this still does not fix the actual issue and is a band-aid at best.

I was actually expecting something like the following to work:

ClassPathResource resource = new ClassPathResource(...);
doReturn(resource.call().getInputStream()).when(someMock).getInputStream();

but unfortunately, this also retrieves the underlying Stream only once.

How can I provide a fresh instance on every doReturn() call? Can mockito even do this? Is there an alternative approach to what I wish to do?

searchengine27 :

I'm not totally sure I'm on board with what you're asking.

You're first doing ClassPathResource resource = new ClassPathResource(...);, which I'm assuming is a one time thing. And then you are returning resource.getInputStream() for every invocation. By definition, you can't have multiple instances then - you're asking for one thing and trying to do another. So what is it that you want? You could use some question restructuring. Also, what are you doing with ClassPathResource in a unit test in the first place?

In the meantime, the best I can guess of what you want is the most literal interpretation of your question that I can get to, and completely ignoring any and all psudeo-code (because it completely contradicts your question). That is, you want a completely separate instance of an InputStream for every invocation to a method. This part is easy.

Mockito.doAnswer(new Answer<InputStream>() {
            @Override
            public InputStream answer(InvocationOnMock invocation)
                    throws Throwable {
                return Mockito.mock(InputStream.class);
            }
        }).when(resource.getInputStream());

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=393677&siteId=1