Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 871
daniu Avatar asked Oct 09 '17 10:10

daniu


1 Answers

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();
}

I have written an article on Mockito Stubbing if you need a further read.

like image 86
Maciej Kowalski Avatar answered Sep 19 '22 13:09

Maciej Kowalski