Mariana Teixeira Mariana Teixeira - 2 months ago 22
Java Question

Can't @InjectMocks attribute call Mockito's method thenReturn?

I started using

Mockito
this week and I'm having a problem to understand
@InjectMocks
field.

I have a class A that is like this:

public class A {

public B b;

public C c;

public String string;

}


when I use it at
JUnit
test with
Mockito
, I call it like this:

@RunWith(MockitoJUnitRunner.class)
public class Test {

@Mock
B b;

@Mock
C c;

@InjectMocks
A a;

...

}


but I want to set the string attribute! I try it like this:

Mockito.when(a.getString()).thenReturn("STRING");


however, the test throws an Exception:


org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public. It is a limitation of the mock engine.


Can I do something else to set this field?

Answer

Can I do something else to set this field?

Yes you can annotate your field with @Spy too as next:

@Spy
@InjectMocks
A a;

Then you will be able to do Mockito.when(a.getString()).thenReturn("STRING");

Indeed when it is annotated with @InjectMocks only ,Mockito doesn't mock it, it creates a normal instance of the class A by default, such that you cannot use Mockito.when() on it. As workaround, you can ask Mockito to partially mock it using @Spy.

The exception that you actually get is due to the case #2 provided in the error message:

inside when() you don't call method on mock but on some other object.