38

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

我试图使 Test 成为 Configuration 组件(带有 @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?

谢谢!

4

2 回答 2

36

是的,你在正确的轨道上,在课堂上模拟@Bean@Configuration一种方法,我将描述我的经历:

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

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

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

至少那是我做同样事情的经验。也许有一些方法可以用模拟版本“覆盖”bean,但到目前为止我还不知道。

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

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

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

如果模拟正在其他地方使用(它们是,这就是你将它们连接起来的原因......)然后initMocks(this)将在测试之间将它们吹走(不是字面意思 - 只是将创建新的模拟并连接任何其他模拟其他对象将“丢失”)。

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

请注意,Mockito 文档reset非常严厉地说这种方法不应该被普遍使用,除非在通过依赖注入应用模拟的上下文中,正如我们在这种情况下确实正在做的那样:)

玩得开心!

于 2013-11-06T10:22:01.803 回答
3

它确实是一个副本

将 Mockito 模拟注入 Spring bean

Springockito-annotation 正是我想要的

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

于 2013-11-06T10:42:43.303 回答