2

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.

1 Answer 1

5

@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);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for introducing me to Spy annotation. The only issue is with the design pattern I am using it does not have any constructors. So the Foo instance does not have an constructor so is never a object. Would there be any other method? When I change to @Spy it returns a nullPointerException - Maybe due to no object being created?
@MTQ If the class has no constructors, it implicitly has a default constructor (i.e., public, with no arguments). Where are you getting the null?
Yes @Spy has fixed this issue. Setting your answer as the correct answer. Thanks
I used: (at)Spy (at)InjectMock MyClass myclass = new MyClass(); I had to provide it instantiated for it to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.