I am new to Mockito, I have tried looking into this Exception but I haven´t found a concrete answer. It happens in my code when I use two mocks together, meaning that I give through the constructor of a mock, another mock. Like so:
...
OperationNode child = getNode(Operation.ADD);
child.insertNode(getConstantNode(getIntegerValue(2));
...
private ConstantNode getConstantNode(NumericalValue value){
ConstantNode node = Mockito.mock(ConstantNode.class);
Mockito.when(node.evaluate()).thenReturn(value);
Mockito.when(node.toString()).thenReturn(value.toString());
return node;
}
private IntegerValue getIntegerValue(int number) {
IntegerValue integerValue = Mockito.mock(IntegerValue.class);
Mockito.when(integerValue.getValue()).thenReturn(number);
Mockito.when(integerValue.toString()).thenReturn(Integer.toString(number));
return integerValue;
}
In one of the forums I read about not sending a mock through a constructor of another mock, since Mockito might get confused with the mock calls, so I tried the following:
NumericalValue value = getIntegerValue(2);
child.insertNode(getConstantNode(value));
But to no avail. I make sure that only the methods toString()
and getValue()
are called, because those are the only methods the class has. I don´t understand what´s going on.
I have also tried using the mocks separately, to see if I have done something wrong:
child.insertNode(new ConstantNode(getIntegerValue(2)));
That works perfectly.
child.insertNode(getConstantNode(new IntegerValue(2)));
That works fine too.
you are trying to stub a final method, which is not supported 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed.
Following are the differences between thenReturn and doReturn : * Type safety : doReturn takes Object parameter, unlike thenReturn . Hence there is no type check in doReturn at compile time. In the case of thenReturn , whenever the type mismatches during runtime, the WrongTypeOfReturnValue exception is raised.
You can use doReturn-when to specify a return value on a spied object without making a side effect. It is useful but should be used rarely. The more you have a better pattern such as MVP, MVVM and dependency injection, the less chance you need to use Mockito. spy .
Mockito 's doNothing() is used when you want to test void methods because void methods do not return anything so there is no way you can verify using assert. These void methods may be anywhere, for example, in service class, in dao class, etc.
From what I read on "Issue 53" of mockito (https://code.google.com/p/mockito/issues/detail?id=53) , my code was experiencing a problem due to the validation framework involved in Mockito. Precisely the following code was causing the exception per se.
private ConstantNode getConstantNode(NumericalValue value){ ConstantNode node = Mockito.mock(ConstantNode.class); Mockito.when(node.evaluate()).thenReturn(value); Mockito.when(node.toString()).thenReturn(value.toString()); return node; }
If you remember from my code, the parameter value is ALSO A MOCK, so that when value.toString()
is called on the thenReturn()
, I believe (and someone please correct me if I am wrong) that the validation framework is triggered and makes sure that every "when" has had its thenReturn()
called/validated/etc. So that if this happenes, the Mockito.when(node.toString()).thenReturn(value.toString()
will not be validated because it hasn´t returned from the valute.toString()
, which started the whole "validate everything" chain.
How I fixed it:
private ConstantNode getConstantNode(NumericalValue value){ ConstantNode node = Mockito.mock(ConstantNode.class); Mockito.when(node.evaluate()).thenReturn(value); String numberToString = value.toString(); Mockito.when(node.toString()).thenReturn(numberToString); return node; }
This way, it can be validated. I find this a complete code smell because I will literally have to leave a comment that explains why I am using a seemingly useless intermediate variable in the code.
Thanks for the help.
There are some good fixes posted in this question already, but for anyone still having trouble understanding it, think of the order in which Java calls all those methods. According to the Java Language Specification, Java evaluates every parameter of a method left-to-right before calling the method:
integerValue.getValue()
, which Mockito recordswhen
, where Mockito takes the last call (to integer.getValue
) and starts setting up stubbingvalue.toString
, which is a mocked call that Mockito recordsthenReturn
on the stubberMockito complains exactly because the call to the mock, step 3, happens after step 2 (when
) but before step 4 (thenReturn
), causing the validation framework to complain about the stubbing. Joy, your answer moves the troublesome step 3 to before step 1, which is fine; Sajan removes it from the statement entirely, which is also fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With