Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

injecting mock beans into spring context for testing

I know similar questions have been asked, e.g. here, but having done a search, I've come upon a solution I'm much happier with here

My only problem however, is that I'm not sure how to implement this solution.

What I want to be able to do is via the HotswappableTargetSource override the bean definitions of select beans in my application context with my test versions and then run the test.

Then for each test case I'd like to specify which beans I want to be hot swappable and then each test must be able to create its own mock versions and swap those in, and be able to swap back again.

I am able to get the Application Context the test is running with but what I don't know is how to configure a bean to be hot swappable. I know how to do it when configuring beans with xml but I don't want to go back to using xml to configure beans.

like image 371
Michael Wiles Avatar asked Nov 25 '10 15:11

Michael Wiles


People also ask

How do you inject a bean in a spring test?

Due to this, we can inject any bean from the application context by autowiring the bean into our test class: @SpringBootTest @TestPropertySource(locations="classpath:test. properties") class TestConfigurationExampleAppTests { @Autowired private DataService dataService; ... }

How do you inject a mock in SpringBootTest?

If you want to create just a Mockito test you could use the annotation @RunWith(MockitoJUnitRunner. class) instead of @SpringBootTest . But if you want to create a Spring Boot integration test then you should use @MockBean instead of @Mock and @Autowired instead of @InjectMocks .

How do you mock a bean in the spring?

We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context. If no bean of the same type is defined, a new one will be added.

How do you mock and inject a mock?

Mockito @InjectMocks annotations allow us to inject mocked dependencies in the annotated class mocked object. This is useful when we have external dependencies in the class we want to mock. We can specify the mock objects to be injected using @Mock or @Spy annotations.


1 Answers

UPDATE: There's a library that does it!

https://bitbucket.org/kubek2k/springockito/wiki/springockito-annotations

The solution is as follows:

You will need to change the spring context of your application to proxy the bean you want to swap:

<bean id="beanSwappable" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="beanSwap" />
</bean>

<bean id="beanSwap" class="org.springframework.aop.target.HotSwappableTargetSource">
    <constructor-arg ref="beanToSwap" />
</bean>
  • beanSwap is the proxy onto this beanSwap.
  • beanSwappable is the bean which you reference when you want to swap the bean
  • beanToSwap is the default implementation of the bean

Thus a change to the system under test is necessary.

And in your test the code will look like:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "test.xml", "spring.xml" })
public class Test {

    @Resource(name="beanSwappable")
    Bean b;

    @Resource(name = "beanSwap")
    HotSwappableTargetSource beanSwap;

    public void swap() {
        Bean b = << create mock version >>
        beanSwap.swap(b);
        // run test code which

    }
}
like image 135
Michael Wiles Avatar answered Sep 28 '22 21:09

Michael Wiles