javamockitospy

Mockito: How to Mock objects in a Spy


The application runs in JEE environment. I wish inject a Spy into a bean under test. The Spy object has also some beans inside that should be injected. How can inject mocks of those beans into the Spy?

This is the usecase:

package testinject2;

import javax.inject.Inject;

public class ABean {

    @Inject
    BBean b;
    
    public void print() {
        System.out.println("Hi, I'm ABean");
        b.print();
    }
}
package testinject2;

import javax.inject.Inject;

public class BBean {

    @Inject
    CBean c;
    
    public void print() {
        System.out.println("Hi, I'm BBean");
        c.print();
    }
}
package testinject2;

public class CBean {

    public void print() {
        System.out.println("Hi, I'm CBean");
    }
}
package testinject2;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)

public class ABeanTest {

    @Spy
    CBean c = new CBean();
    
    @Spy
    BBean b = new BBean();
    
    @InjectMocks
    ABean beanUnderTest;
    
    @Test
    public void test() {
        beanUnderTest.print();
    }
}

I'm expect to obtain

Hi, I'm ABean
Hi, I'm BBean
Hi, I'm CBean

But instead I have a null ponter exception because CBean is not injected into BBean.

Which is the correct way to Inject a Spy object into another Spy ?


Solution

  • You need to define to which object mocks should be injected via @InjectMocks annotation, but it does not work together with @Spy annotation. See mockito issue.
    There is the simplest solution to use Mockito.spy instead of @Spy together with @InjectMocks:

        @InjectMocks
        BBean b = Mockito.spy(new BBean());
    

    Full test code:

    @RunWith(MockitoJUnitRunner.class)
    public class ConfigTestObject {
    
        @Spy
        CBean c = new CBean();
    
        @InjectMocks
        BBean b = Mockito.spy(new BBean());
    
        @InjectMocks
        ABean beanUnderTest;
    
        @Test
        public void test() {
            beanUnderTest.print();
        
            //verify that mocks is working
            verify(c, atLeast(1)).print();
            verify(b, atLeast(1)).print();
        }
    }