I am using InjectMocks
and Spy
annotations for injecting a prototype bean.
However the inject bean behaves like singleton bean. Is there any way to inject a prototype scoped bean in Mockito?
I am running JUnit with SpringJUnit4ClassRunner
and init mocks using MockitoAnnotations.initMocks(this)
.
You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
Let us look at a simple example when a prototype bean injected inside a singleton bean. Individually when a prototype bean used, every time a new instance is expected and for singleton the same instance. Singleton Bean always returns the same bean instance no matter where ever it is being referred.
When you autowire a prototype bean, Spring will initialize a new instance of the bean. If you autowire the bean in multiple places, then Spring will create a new instance for every place you autowire the bean. Let us demonstrate this behavior by creating a test bean and a spring test where we autowire our test beans.
That's because Mockito creates your injected objects at compile time. If you want a prototype-like behavior, you need to switch to using answers.
For example, assume that your Spring application has a prototype bean called Foo and your code is doing something like this multiple times:
ctx.getBean("Foo");
Since Foo is a prototype, every time getBean() is called, a new instance of Foo is returned by Spring.
Now, in your Mockito test you mocked the ctx to spoof the getBean() and return your own pre-configured instance of Foo.
if you set up your test like below, no matter how many times your code calls ctx.getBean(), the same instance of Foo will be returned:
Foo foo = new Foo();
decorateFoo(foo);
when(ctx.getBean("Foo")).thenReturn(foo);
This is how you can achieve a prototype-like behavior in your test:
when(ctx.getBean("Foo")).then(new FooAnswer());
private class FooAnswer implements Answer<Foo> {
@Override
public Foo answer(InvocationOnMock invocationOnMock) throws Throwable {
return new Foo(); // and configure as needed
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With