WrongTypeOfReturnValue when nesting when().thenReturn

37,888 views
Skip to first unread message

ludyte

unread,
Sep 30, 2011, 2:57:14 PM9/30/11
to mockito
OK, this is twisty and it took me a while to refine it into the
attached code. So when you read the following description and it
doesn't make any sense, look at the code. Run the code and see the
error.

I get a WrongTypeOfReturnValue exception if I create a
when().thenReturn() condition on a method and the return value is a
mock of class Product. Where Product has a constructor that takes
type Foo. This only happens if there exists a mock on an instance of
Foo and that mock has a when().thenReturn() for a type Bar. And Bar
is extracted from the Foo passed into the constructor of Product. And
the constructor for the object containing the original method takes
that mock of Foo as an argument. Don't bother reading that again,
just scroll down to the source.


---CONSOLE TEXT----

bash-3.2$ javac -cp lib/mockito-all-1.9.0-rc1.jar:lib/junit-4.9.jar
NestedWhen.java
bash-3.2$ java -cp .:lib/mockito-all-1.9.0-rc1.jar:lib/junit-4.9.jar
org.junit.runner.JUnitCore NestedWhen
JUnit version 4.9
.E
Time: 0.202
There was 1 failure:
1) nestedWhenTest(NestedWhen)
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
NestedWhen$Product$$EnhancerByMockitoWithCGLIB$$6ecf83da cannot be
returned by getBar()
getBar() should return Bar
***
This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.

at NestedWhen.nestedWhenTest(NestedWhen.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at <SNIP the usual JUnit stuff>

FAILURES!!!
Tests run: 1, Failures: 1

---TEST SOURCE---

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;

import org.junit.Test;

public class NestedWhen
{
public class Bar{}
public class Foo{
Bar getBar(){ return new Bar(); }
}

public class Product
{
Bar bar;
Product( Foo f ){ bar = f.getBar(); }
}

public class Outside
{
Foo foo;
Outside( Foo f ){ foo = f; }
Product produce(){ return new Product(foo); }
}

@Test
public void nestedWhenTest()
{
Foo mfoo = mock( Foo.class );
Product mpoo = mock( Product.class );
Outside out = spy(new Outside( mfoo ));
//raises WrongTypeOfReturnValue exception here!!!
when( out.produce() ).thenReturn( mpoo );
}
}

Brice Dutheil

unread,
Oct 1, 2011, 10:23:06 AM10/1/11
to moc...@googlegroups.com
Hi,

Well actually the issue in your code resides with the spy.

Here is the explanation what's happening with your code.
  1. A spy actually execute the real code by nature, so when calling "out.produce()" the expression is actually executed and return a real Product.
  2. The constructor of Product takes the constructor arg "foo" which is a mock and it executes "f.getBar()". This invocation is recorded by mockito because this "foo" instance is a mock.
  3. Then when you want to return "mpoo", mockito raises the exception WrongTypeOfReturnValue saying that the recorded invocation "foo.getBar()" cannot return a Product.

If you want to mack a partial mock, which you should avoid if possible. You need to use the following style for spies, this way mockito can tell the spy instance to only record the invocation.

doReturn(mpoo).when(out).produce();

Hope that helps.


-- 
Brice



--
You received this message because you are subscribed to the Google Groups "mockito" group.
To post to this group, send email to moc...@googlegroups.com.
To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mockito?hl=en.


Han Li

unread,
Apr 3, 2016, 5:58:03 AM4/3/16
to mockito
Great. Thanks for the explanation. 
Reply all
Reply to author
Forward
0 new messages