MTQ
MTQ

Reputation: 33

How can I mock methods that are also in @InjectMocks class?

I am doing JUnit tests with Mockito on Spring Mvc. The tests are using @InjectMock and @Mock with when(method(..)).thenReturn(X). The issue is how to @Mock methods that are within a @Inject instance?

I have tried creating two instances such as @InjectMocks Foo fooInstance and @Mock Foo fooInstanceMock; My way of thinking is to differentiate from what instance to inject and what to mock. I also tried using Spy with InjectMocks but it returns a exception.

Actual Class Syntax-

class Foo {
    public X(..) {
        ...
        Y(...); // method call to Y
        ...
    }

    public Y(..) {
        ...
    }
}

Test Syntax -

public class FooTest {
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @InjectMocks
    Foo fooInstance;

    @Mock
    Foo fooInstanceMock;

    @Test
    public void xTest{
        when(fooInstanceMock.Y(..)).thenReturn(true);
        Boolean result = fooInstance.X(25);
        Assert.assertTrue(result == true)
    }
}

I except the output to be true as when then return true but since it thinks it is a injectMock and it goes into the implementation.

Upvotes: 2

Views: 7156

Answers (1)

Mureinik
Mureinik

Reputation: 311228

@InjectMocks is used to inject mocks you've defined in your test in to a non-mock instance with this annotation.

In your usecase, it looks like you're trying to do something a bit different - you want a real intance of Foo with a real implementation of x, but to mock away the implmentation of y, which x calls. This can be done by partial mocking, or in Mockito's terminology, spying:

public class FooTest{

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    // Default constructor is used to create a real Foo instance.
    // In the test's body, though, we'll override the behavior of SOME of the methods
    @Spy
    Foo fooInstance;

    @Test
    public void xTest {
        doReturn(true).when(fooInstance).y(/* arguments, presumably 25 */);
        Boolean result = fooInstance.x(25);
        Assert.assertTrue(result);
    }
}

Upvotes: 5

Related Questions