自动化bean实现相同的接口 - 如何在JUnit测试中自动装配特定的依赖bean?

时间:2012-05-11 14:56:27

标签: spring junit easymock autowired

我有一个Spring 3.1 / Java / Tomcat应用程序。我有一个服务类如下:

public class SomeServiceImpl implements SomeService {

  @Autowired
  public AnotherService anotherService;

  //  other code...

这使用另一个自动装配的服务类AnotherService。这两个服务类都在serviceContext.xml文件中声明。

我正在编写junit来测试SomeServiceImpl并使用autowired来注入测试类(SomeService)以及被测试类(AnotherService)所需的mock(EasyMock)依赖项。 AnotherService的easymock依赖项在testContext.xml中定义,如下所示:

    <bean id="mockAnotherService" class="org.easymock.EasyMock" factory-method="createMock" primary="true">
        <constructor-arg value="com.xyz.AnotherService" />
    </bean>

在我的测试类中,我配置为使用上下文文件。但是,我看到ServiceImpl正确地连接到实际的实现(这是期望的)但是,而不是AnotherService的模拟版本,concreate版本(AnotherServiceImpl)正在连接。

如何让我的依赖项的模拟版本变为有线?我不能在实际实现中使用@Resource或@Qualifier,因为这会破坏目的。我可以在我的测试课中使用它们。

2 个答案:

答案 0 :(得分:2)

如果它们都在serviceContext.xml中声明,并且您想要模拟其中一个,则该文件无法用于测试。拆分它以便您可以使用其中一个“真正的”Spring上下文文件与包含模拟的测试上下文相结合,或者只是手动创建bean并使用setter方法设置AnotherService。控制反转的一个优点是允许您手动创建bean并以这种方式注入依赖项。

答案 1 :(得分:1)

您可以将serviceContext.xml导入testContext.xml,然后仅在测试用例中引用textContext.xml,而不是配置为同时使用上下文文件。

将配置文件导入另一个文件时,另一个文件有机会覆盖导入文件中的bean定义。

确保模拟的id与您的类相同 - 否则它将创建两个不同的bean。另一个问题是模拟对象没有公布正确的接口类型 - 因此按类型自动装配可能会失败。要解决该问题,您需要执行以下操作。我正在使用这种方法与mockito - 也应该为简单的模拟工作。

<bean id="anotherService" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
     <bean class="org.easymock.EasyMock" factory-method="createMock" primary="true">
        <constructor-arg value="com.xyz.AnotherService" />
    </bean>
    </property>
    <property name="proxyInterfaces">
      <value>com.xyz.AnotherService</value>
    </property>
  </bean>

尝试的另一件事是在类中创建创建模拟对象的Java Config样式方法。如果直接在测试类中创建它不起作用,你可以使用带有@Configuration的另一个类来创建模拟,然后在testContext.xml中将其定义为bean

  @Bean
  AnotherService anotherService() {
      return EasyMock.createMock(AnotherService.class);
  }