如何在Spring上下文中注入模拟

时间:2013-11-06 09:31:32

标签: java spring dependency-injection mocking mockito

我有一个使用一些Spring上下文的测试。在这些上下文中,声明了许多bean。 我希望测试使用上下文bean的实际实现,除了其中一个,我想使用MOCK。

我尝试将Test作为一个配置组件(使用@Configuration注释),但XML似乎优先于@Bean注释,所以它不起作用,这样:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"context1.xml", "context2.xml", ...})
@Configuration
public class MyTest{

    @Inject
    private MyTargetBean target;

    private AnotherBean myMock = mock(AnotherBean.class);

    @Bean
    public AnotherBean myMock() { return myMock; }

    .....

我知道我可以用XML定义Mocks,但为此我需要为每个测试添加一个额外的XML文件,我希望在其中执行此操作。我想避免这种复杂性。

有没有办法在上下文中注入bean(比如模拟)而不是通过XML?

谢谢!

2 个答案:

答案 0 :(得分:34)

是的,你走在正确的轨道上,在@Bean课程中放置一个模拟@Configuration是一种方法,我将描述我的经历:

诀窍是你需要使用一组不同的.xml文件纯粹用于测试,这些文件排除了这些bean的实时版本。

@ContextConfiguration(locations = {"context1-test.xml", "context2-test.xml", ...})

“-test-xml”文件进入src/test/resources

至少那是我做同样事情的经验。也许有一些方法可以用模拟版本“覆盖”bean,但是我还没有意识到它。

我还选择将mocks(我有5个)放在一个自己的配置中:

@Configuration
public class MockServicesProvider {
     @Bean
     public AnotherBean myMock() { return mock(AnotherBean.class); }
}

此问题的另一个有趣部分是initMocks(this);在测试类的@Before方法中的常见用法。

如果在其他地方使用模拟(它们就是这样,那就是你为什么要将它们连接起来......)那么initMocks(this)会在测试之间将它们吹掉(不是字面意思 - 只是新的模拟将是创建和其他对象中连接的任何其他模拟都将“丢失”。)

解决方法是在每次测试之前在reset(mockObject)方法中调用mockito的@Before。重置相同的模拟(所有when和交互),而不创建新的模拟。

请注意,reset的Mockito文档非常严格地说,通常不应该使用此方法,除非在通过依赖注入应用模拟的上下文中,因为我们确实在这种情况下执行:)

玩得开心!

答案 1 :(得分:3)