Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 945
mhery Avatar asked Sep 09 '16 15:09

mhery


1 Answers

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.

like image 57
Nicolas Filotto Avatar answered Oct 14 '22 02:10

Nicolas Filotto