Injecting mock into Spring container without xml for testing
Currently I have my spring application wired up using @Autowired, @Component, @Resource etc. Now I want to write a test that requires the mocking of specific objects in the system but retaining the real production wiring of the remaining objects.
Let's say the root object being tested is called Foo. Deeper down the dependency chain, Foo depends on Bar. Currently to mock out this object, I have created a test-applicationContext.xml that has just the single bean entry of:
<bean id="bar" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Bar" />
</bean>
The test-applicationContext.xml is declared in the @ContextConfiguration annotation and therefore Foo will ultimately depend on the mocked Bar object.
Is it possible to get the same result without having to have this test-applicationContext.xml? i.e. do the same but progrmatically?
So in pseudo code, I was wondering if I could have something like:
开发者_运维知识库public class MyTest {
@Test
public void simple() {
// create mock Bar object
// register mock Bar object in container
// resolve Foo object with all its dependencies but use the mock Bar object instead of the real one
// set some expectations on the Bar object
// call some method on Foo
}
}
You have to avoid starting the Spring context in your unit tests. Use the Spring context only in tests that check properties injection and other Spring features. Then, you will be able to create programatically mock objects.
Althought, it can be done with something like:
BeanDefinitionRegistry registry = ((BeanDefinitionRegistry )factory);
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBeanClass.class);
beanDefinition.setLazyInit(false);
beanDefinition.setAbstract(false);
beanDefinition.setAutowireCandidate(true);
beanDefinition.setScope("session");
registry.registerBeanDefinition("dynamicBean",beanDefinition);
Just inject your BeanFactory in your JUnit to get the factory
One way to do it:
In your test context, component-scan the bare minimum.
@Autowire the dependencies of Bar into your test class.
In your SetUp:
Manually
new Bar()
Create mock of Foo
Set properties of new Bar including the @Autowired (first #2) and mock (second #2).
I had a very similar problem and used https://bitbucket.org/kubek2k/springockito/wiki/Home that was really heplful to me.
In your case you can use if you want total mock then use @ReplaceWithMock or you can use @WrapWithSpy which will do partial mock and only you can mock the function you want to change the behaviour of.
精彩评论