In the code below I expect that given
will throw MissingMethodInvocationException
as foo()
is final.
But instead I get NullPointerException
at str.equals("String 1")
.
So, Mockito is calling real code. Why?
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
class Foo {
private String str = "String 1";
public final String foo() {
if (str.equals("String 1")) {
str = "String 2";
}
return str;
}
}
@RunWith(MockitoJUnitRunner.class)
public class TestClass {
@Mock
Foo foo;
@Test
public void test() {
given(foo.foo()).willReturn("x");
assertEquals("x", foo.foo());
}
}
In the example below, I removed the if clause. Now it works as expected.
Of course I don't want to remove those lines as they are needed in the code I'm testing.
How is presence of that lines affecting Mockito's behaviour?
public final String foo() {
return str;
}
How can I make sure that Mockito will never call real code on methods even if they happen to be final?
I'd rather see MissingMethodInvocationException
.
And in this code, the test passes:
public String foo() {
if (str.equals("String 1")) {
str = "String 2";
}
return str;
}
The reason I am asking is that I have a test case and someone added final
modifier to one of the methods being tested/mocked.
Instead of seeing MissingMethodInvocationException
we saw some unrelated Exceptions thrown from 'real' code inside mocked method. We spent some time looking for the place and change that caused tests to fail.
If Mockito threw MissingMethodInvocationException
we would see the reason instantly.