在单元测试中覆盖自动装配的Bean

时间:2015-02-19 12:00:35

标签: spring spring-boot spring-annotations

有一种简单的方法可以在特定的单元测试中轻松覆盖自动装配的bean吗?在编译类中只有一个类型的bean,因此在这种情况下它不是自动装配的问题。测试类将包含额外的模拟。在运行单元测试时,我只想指定一个基本上说的附加配置,在运行此使用测试时使用此模拟而不是标准bean。

配置文件似乎对我的要求有点过分,我不确定使用Primary注释可以实现这一点,因为不同的单元测试可能会有不同的模拟。

6 个答案:

答案 0 :(得分:65)

如果您只是想在测试中提供不同的bean,我认为您不需要使用spring profile或mockito。

请执行以下操作:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { TestConfig.class })
public class MyTest
{
    @Configuration
    @Import(Application.class) // the actual configuration
    public static class TestConfig
    {
        @Bean
        public IMyService myService()
        {
            return new MockedMyService();
        }
    }

    @Test
    public void test()
    {
        ....
    }
}

注意:使用弹簧靴1.3.2 /弹簧4.2.4进行测试

答案 1 :(得分:42)

在Spring Boot 1.4中,有一种简单的方法:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MyApplication.class })
public class MyTests {
    @MockBean
    private MyBeanClass myTestBean;

    @Before
    public void setup() {
         ...
         when(myTestBean.doSomething()).thenReturn(someResult);
    }

    @Test
    public void test() {
         // MyBeanClass bean is replaced with myTestBean in the ApplicationContext here
    }
}

答案 2 :(得分:5)

我有类似的问题,我用混合物解决了,我发现这个更有用和可重复使用。我为测试创建了一个spring配置文件,并以一种非常简单的方式覆盖了我想要模拟的bean的配置类:

@Profile("test")
@Configuration
@Import(ApplicationConfiguration.class)
public class ConfigurationTests {

    @MockBean
    private Producer kafkaProducer;

    @MockBean
    private SlackNotifier slackNotifier;

}

通过这样做,我可以@Autowire那些模拟豆,并使用mockito来验证它们。主要优点是,现在所有测试都可以无缝地获取模拟bean而无需进行任何测试更改。 经测试:

  

spring boot 1.4.2

答案 3 :(得分:1)

您应该使用spring配置文件,以了解您想在不同的上下文中使用哪种bean。

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

答案 4 :(得分:0)

正如mats.nowak所说,response.Payload对此很有用。

假设一个父测试类是:

@ContextConfiguration

创建一个子测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/some-dao-stuff.xml"
    ,"classpath:spring/some-rest-stuff.xml"
    ,"classpath:spring/some-common-stuff.xml"
    ,"classpath:spring/some-aop-stuff.xml"
    ,"classpath:spring/some-logging-stuff.xml"
    ,"classpath:spring/some-services-etc.xml"
})
public class MyCompaniesBigTestSpringConfig {
...

并放入src / test / resources / x / y / z / MyOneOffTest-context.xml

package x.y.z;
@ContextConfiguration
public class MyOneOffTest extends MyCompaniesBigTestSpringConfig {
...

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="widgetsService" class="com.mycompany.mydept.myservice.WidgetsService" primary="true" /> </beans> bean将覆盖(代替)主配置xml(或Java配置)中定义的bean。请参阅关于inheritLocations 另请注意默认的-context.xml文件。该here的示例。 更新:我必须添加widgetsService,显然这是必需的。

答案 5 :(得分:0)

从 Spring Boot 1.4.0 开始,而不是为测试显式指定 @Configuration,只需添加用 @TestConfiguration 注释的静态嵌套类,并提供用 @Bean 注释的替代 @Primary

@TestConfiguration 将被添加到您的主要 Spring Boot 测试上下文(这意味着您的生产 bean 仍将被创建),但将使用来自 @TestConfiguration 的那个,因为 {{1} }.