Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Inject Prototype bean in Mockito

Tags:

spring

mockito

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).

like image 269
Rajesh Kolhapure Avatar asked May 25 '17 14:05

Rajesh Kolhapure


People also ask

Can we inject a prototype bean into a singleton bean?

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.

What will happen if prototype bean is injected in singleton Bean?

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.

Can we Autowire prototype bean?

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.


1 Answers

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
    }
}
like image 182
Oleg T Avatar answered Nov 11 '22 22:11

Oleg T