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

问题描述 投票:0回答:7

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

配置文件对于我的要求来说似乎有点过大,我不确定这是否可以通过主要注释来实现,因为不同的单元测试可能有不同的模拟。

spring spring-boot spring-annotations
7个回答
89
投票

如果你只是想在测试中提供不同的bean,我认为你不需要使用spring配置文件或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()
    {
        ....
    }
}

注意:使用 Spring Boot 1.3.2 / Spring 4.2.4 进行测试


52
投票

在 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
    }
}

7
投票

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

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

    @MockBean
    private Producer kafkaProducer;

    @MockBean
    private SlackNotifier slackNotifier;

}

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

春季启动1.4.2


4
投票

自 Spring Boot 1.4.0 起,无需显式指定

@Configuration
进行测试,只需添加用
@TestConfiguration
注释的静态嵌套类,并提供用
@Bean
注释的替换
@Primary

@TestConfiguration
将被添加到您的主要 Spring Boot 测试上下文中(这意味着您的生产 bean 仍将被创建),但由于
@TestConfiguration
,将使用
@Primary
中的那个。


3
投票

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

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


0
投票

请参阅我在另一篇文章中的回答,了解执行 bean 覆盖测试的正确方法。我认为 @Primary 是一个 hack,如果它已经有商业用途,甚至可能无法使用。

避免使用 @MockBean 以允许通过 bean 覆盖重用 spring-context


-1
投票

正如 mats.nowak 评论的那样,

@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 {
...

创建子测试类:

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

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

<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>

widgetsService
bean 将覆盖(取代)主配置 xml(或 Java 配置)中定义的 bean。请参阅inheritLocations 另请注意默认的 -context.xml 文件。例子这里。 更新:我必须添加
primary="true"
,显然这是需要的。

© www.soinside.com 2019 - 2024. All rights reserved.