Search code examples
javaspringunit-testingjunitmockito

Mockito: How to mock javax.inject.Provider-created prototype beans?


I have a singleton Spring bean which creates prototype beans; those are retrieved from a javax.inject.Provider field:

@Component
public class MySingleton {
    @Autowired
    private javax.inject.Provider<MyPrototype> prototypeFactory;

    public void doStuff() {
        MyPrototype bean = prototypeFactory.get();
        bean.invoke();
    }
}

@Component
@Scope("prototype")
public class MyPrototype {
    public void invoke() {}
}

Now I would like to create a JUnit-Test for the Singleton:

@Mock 
MyPrototype prototype;
@InjectMocks 
MySingleton sut;
@Test
public void testPrototype() {
    sut.doStuff();
    verify(prototype, times(1)).invoke();
}

But that understandably doesn't properly setup the Singleton's Provider.

Is there any way to do that? I'd like to avoid creating a Singleton Factory bean which creates the Prototype instances.

Or, would it maybe be elegantly possible using a @Lookup-factory method for the Singleton? I haven't looked into that at all yet.


Solution

  • I would stub that Provider and make it return the prototypeMock every time using the @Before method invoked before each of the tests:

    @Mock
    private javax.inject.Provider<MyPrototype> prototypeFactoryStub;
        
    @Mock 
    MyPrototype prototypeMock;
    
    @InjectMocks 
    MySingleton sut;
    
    @Before
    public void init(){
       MockitoAnnotations.initMocks(this); // optional
    
       when(prototypeFactoryStub.get()).thenReturn(prototypeMock);
    }
    
    @Test
    public void testPrototype() {
        sut.doStuff();
        verify(prototypeMock, times(1)).invoke();
    }