【问题标题】:Spring / Mock components that are retrieved by using the context directly直接使用上下文检索的 Spring / Mock 组件
【发布时间】:2014-06-20 11:39:51
【问题描述】:

我们有一个项目使用Spring 注解来配置它的上下文。 为了测试这个项目,我们使用了Mockito,它是Spring 扩展。

在测试中,我需要用模拟/间谍版本覆盖一些 bean。

通过 @Mock/@Spy@InjectMock 注释,我已经能够使用自动装配机制对 bean 使用 spy。

现在我有一个第三方组件,它创建另一个 Spring 上下文,然后将这 2 个上下文合并在一起。此第三方组件使用对上下文的调用来检索 bean:

applicationContext.getBean(key);

在这种情况下,@Mock/@Spy 和 @InjectMock 组合不起作用。

我采用的“解决方法”解决方案是一个 XML 文件,我在其中声明了我的间谍 bean:

<mockito:spy beanName="beanToSpy"/>

为了留在注释世界中,我尝试了springockito-annotations,如以下类似问题中所述: Injecting Mockito mocks into a Spring bean 及其副本: How to inject a Mock in a Spring Context

但是 bean 没有被监视或模拟,我可能有一个配置错误。

我目前的设置是:

一个负责测试 Spring 配置的基类:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(loader= SpringockitoContextLoader.class, locations ={"/config.xml","/test-config.xml"})
public abstract class BaseTest {
  //...
}

想要使用模拟 bean 的测试类:

public class MyTest extends BaseTest {
  @ReplaceWithMock @Autowired MyService myService;
  @WrapWithSpy @Autowired OtherService otherService;

  @Test public void someTest() { 
    doReturn(x).when(myService).call();
    doReturn(y).when(otherService).process();
  }
}

不幸的是,在MyTest 中,bean 没有被它们的mock/spy 版本替换,它是普通的旧常规版本。

编辑: 进行查找的第三方组件使用它自己的 spring 父上下文并将当前的 spring 上下文添加到它自己的上下文中。检索我想要模拟的组件的查找发生在上下文完全加载后。

我应该怎么做才能用mock/spy 版本正确替换上下文中的bean? 我使用@WrapWithSpy / @ReplaceWithMock 的方式有什么问题?

【问题讨论】:

  • 所以 的解决方案有效,您想用注释替换它吗?
  • @frant.hartm 是的,我再也睡不着了;)

标签: java spring testing mockito


【解决方案1】:

什么时候调用

applicationContext.getBean(key);

发生了吗?是否有可能在 SpringockitoContextLoader 有机会用间谍替换它之前检索 bean?

留在注释世界的一个解决方案是覆盖 java config 中的 bean:

@Bean
public MyBeanType myBeanType() {
    return spy(new MyBeanType(...))
}

【讨论】:

  • 谢谢,我会试试这个选项,我会告诉你。
【解决方案2】:

执行此操作的更传统方法是根据需要在测试中简单地模拟它们:

public class MyTest extends BaseTest {
    @Test public void someTest() { 
        MyService myMockService = Mockito.mock(MyService.class);
        // define when's
       // perform verification
      }

你可以使用 SpringReflectionTestUtils 进行注入,或者如果使用 setter 注入就正常设置。

如果您在包含多个测试的测试类中使用全局模拟 bean,结果可能会令人困惑。

【讨论】:

  • 我想要的是一个全局模拟bean。这很好,因为每个测试之间都会刷新上下文(@DirtiesContext)。我需要这个,因为我没有直接测试组件;模拟服务将被有权访问上下文的第三方组件检索和使用。我需要“窥探”服务,所以当第三方组件使用它时,我可以测试它的行为方式。 (我们正在测试 activiti 工作流程,这就是我们有这个设置的原因)
猜你喜欢
  • 2017-11-29
  • 2014-09-29
  • 2011-07-18
  • 1970-01-01
  • 2011-05-24
  • 2013-11-17
  • 1970-01-01
  • 2013-01-15
  • 2017-04-06
相关资源
最近更新 更多