In this post, we will see how to fix Org.Mockito.Exceptions.Misusing.WrongTypeOfReturnValue.
There are two major reasons because of which you can get this Exception. These details are provided in Exception itself.
- This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing.
- A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies – with
doReturn|Throw()
family of methods. More in javadocs for Mockito.spy() method.
💡 Quick fix
If you are looking for quick solution, then you should change
when() and thenReturn()
combination todoReturn() and when()
while calling a method on Spy.
123 when(factory.produce()).thenReturn(car);To
123 doReturn(car).when(factory).produce();Here
factory
is spy object.
Here is an example where we will reproduce the issue and fix it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package org.arpit.java2blog; class EngineParts{ } class Engine{ public EngineParts getEngineParts() { return new EngineParts(); } } class Car{ EngineParts engineParts ; public Car(Engine engine) { engineParts = engine.getEngineParts(); } } public class Factory { Engine engine; Factory(Engine engine) { this.engine=engine; } public Car produce() { return new Car(engine); } } |
Mockito testcase:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package org.arpit.java2blog; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class MockitoTestFactory { @Test public void testProduce() { Car car = mock( Car.class ); Engine engine = mock(Engine.class); Factory factory = spy(new Factory(engine)); // It will throw WrongTypeOfReturnValue Exception when( factory.produce()).thenReturn( car ); } } |
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: Car$MockitoMock$425501412 cannot be returned by getEngineParts() getEngineParts() should return EngineParts *** If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because: 1. This exception *might* occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing. 2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method. at org.arpit.java2blog.MockitoTestFactory.testProduce(MockitoTestFactory.java:23) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) ... |
Once you change following line, you won’t get exception anymore.
1 2 3 |
when(factory.produce()).thenReturn(car); |
To
1 2 3 |
doReturn(car).when(factory).produce(); |
Let’s understand why did we get this exception.
- When you use spy, real code is executed by nature, so when we are calling
factory.produce()
, it is getting executed and returning a realCar
object. - Constructor of Car has constructor agrument as
engine
(mock object) and it callsengine.getEngineParts()
. This invocation is recorded by mockito asengine
is a mock object. - Then when we want to return
car
, mockito throws the exception WrongTypeOfReturnValue complaining that the recorded invocation "engine.getEngineParts()" cannot return a Car.
So you should avoid using when() and thenReturn() in case of spy()
as it calls actual method which may have side effects.
You should always use doReturn()
or doThrow()
with when()
while dealing with spies.
Here is another example where we can have side effects of calling actual method while using when()
and thenReturn()
1 2 3 4 5 6 7 |
List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); |
Output
1 2 3 4 5 6 7 8 9 10 |
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248) at java.base/java.util.Objects.checkIndex(Objects.java:372) at java.base/java.util.ArrayList.get(ArrayList.java:459) at org.arpit.java2blog.MockitoTestFactory.TestList(MockitoTestFactory.java:33) |
As you can see, here real method is called and test throws IndexOutOfBoundsException
. We can avoid this issue by changing highlighted line to:
1 2 3 4 |
//You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0); |
You might also get this exception while mocking final methods. You can not mock final methods using Mockito.
That’s all about how to fix Org.Mockito.Exceptions.Misusing.WrongTypeOfReturnValue
Exception in Mockito.