When I Run Mockito Test Occurs Wrongtypeofreturnvalue Exception

WrongTypeOfReturnValue error while unit testing

This line is wrong:

when(bookRepository.findById(book.getId()).orElse(null)).thenReturn(book);

orElse() isn't a method on your mock object, it's a method belonging to Optional... The line should be:

when(booRepository.findById(book.getId())).thenReturn(Optional.of(book));

Mockito WrongTypeOfReturnValue: Boolean cannot be returned by findById()

In the init method, you are stubbing findById on the mock instance this.petRepository to return a non-mock Optional, which is good. In your new test, you are trying to set a return value for isPresent, which you can't do because Optional is not a mock. If you want to override the behavior per-test, you'll need to stub findById to return an Optional of a different instance. Therefore, this is right, though it appears exactly as it does in init and consequently it can't tell you why your test is failing.

Mockito.when(this.petRepository.findById(0))
.thenReturn(java.util.Optional.of(pet));

Mockito works by creating a mock object that subclasses a class and overrides every method. The overridden method is what interacts with a static (ThreadLocal) infrastructure, allowing you to use when syntax. The important thing here is that when ignores its argument, and instead tries to mock the last interaction that you made with a mock. You can find out more in the SO questions How does mockito when() invocation work? and How do Mockito matchers work?.

When you see this call:

Mockito.when(this.petRepository.findById(0))
.thenReturn(java.util.Optional.of(pet));

Then it works as you've intended:

  1. petRepository is a mock, findById is presumably an overridable method, Mockito records the fact that you've called it with the argument 0.
  2. findById doesn't have any behavior stubbed yet, so it does its default, returning null.
  3. when doesn't care that it just received null, because the null doesn't tell it anything about what methods were called to get the null. Instead it looks back at its most recent record (findById(0)) and returns an object with the thenVerb methods you expect.
  4. You call thenReturn, so Mockito sets up petRepository to return the Optional instance you created and passed in.

But when you try this call:

Mockito.when(this.petRepository.findById(0).isPresent()).thenReturn(true);

Then the most recent interaction isn't isPresent, it's findById, so Mockito assumes you want findById(0) to thenReturn(true) and throws WrongTypeOfReturnValue. Optional is not a mock, so interacting with it doesn't let Mockito record its interaction or replay your behavior. For what it's worth, I also wouldn't advise mocking it: Optional is a final class, and though Mockito has recently added some support for mocking final types, Optional is simple and straightforward enough that it makes more sense to just return the Optional instance you want rather than trying to mock it.

With all that said, your code looks right; as long as PetRepository is an interface I don't see anything about the way your method looks or the way your mocks look that would cause this.petRepository.findById(0) to return an absent Optional. In fact, I don't even see where you would create an absent Optional for it to return, so I can only guess that you are using more real objects in your test than you think you are.

android testing - mockito error org.mockito.exceptions.misusing.WrongTypeOfReturnValue:

talkService isn't a mock. Even though you have this set:

@Mock
TalkService talkService;

You then overwrite it in your @Before method setUp:

talkService = ServiceFactory.createMapi(createTalkMvpView.getContext(), TalkService.class);

So in your test, this happens to a real TalkService implementation:

when(talkService.createNewTalk(/* ... */
)).thenReturn(Observable.just(talkResultModel));

Which then calls a real createNewTalk method, which starts with this:

mApiTalkService = ServiceFactory.createMapi(
createTalkMvpView.getContext(), TalkService.class);

The rest of the method isn't important, because Mockito's when works by mocking the last method that was called before/within the call to when, and nothing else in that method interacts with mocks. If talkService were a mock, then when(talkService.createNewTalk(/*...*/)) would stub the method createNewTalk, but instead it stubs that last mock method call getContext. This makes it look like:

when(createTalkMvpView.getContext()).thenReturn(Observable.just(talkResultModel));

...which exactly matches your error message:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ScalarSynchronousObservable cannot be returned by getContext()


To fix this, just remove your talkService assignment so the when method call is actually a mock, or use a real talkService as you've initialized it and remove the @Mock annotation and when and verify statements.

Proper way to test POST service which may throw exception using Mockito?

Mock readingService so that readingService.findByClientAndYearAndMonth returns an Optional that represents some value, i.e. reading.isPresent() is true.

something like:

Client client = ...
ReadingServiceClass readingService = Mockito.mock(ReadingServiceClass.class);
Mockito
.when(readingService.findByClientAndYearAndMonth(client, 10, 2020))
.thenReturn(Optional.of(new Reading(...)));
// ... inject readingService into objectToTest
try {
objectToTest.addReadings(1, 2020, 10, 1.0d);
Assert.fail();
} (catch IllegalModificationException e) {
// ... assert details of exception
}


Related Topics



Leave a reply



Submit