有没有一种简单的方法可以在特定的单元测试中轻松地覆盖自动装配的bean? 在编译类中只有每种类型的一个bean,因此在这种情况下进行自动连接不是问题。测试类将包含其他模拟内容。 运行单元测试时,我只想指定附加配置,即在运行此单元测试时使用此模拟而不是标准bean。
针对我的要求,配置文件似乎过于复杂,并且我不确定是否可以通过Primary注释来实现,因为不同的单元测试可能具有不同的模拟。
有没有一种简单的方法可以在特定的单元测试中轻松地覆盖自动装配的bean? 在编译类中只有每种类型的一个bean,因此在这种情况下进行自动连接不是问题。测试类将包含其他模拟内容。 运行单元测试时,我只想指定附加配置,即在运行此单元测试时使用此模拟而不是标准bean。
针对我的要求,配置文件似乎过于复杂,并且我不确定是否可以通过Primary注释来实现,因为不同的单元测试可能具有不同的模拟。
@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 进行测试。
@Import
注解是用来做什么的?只有在测试配置中需要使用现有的bean时才需要吗? - augurar@Primary
注解来覆盖原始Bean(spring-boot-starter-parent:2.0.0.RELEASE,spring-boot-starter-test:2.0.4.RELEASE);谢谢 @Kacper86。 - Murukan在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
}
}
MyApplication
是什么? - Krzysztof Krasoń@MockBean
生效,你需要使用 @TestExecutionListeners(MockitoTestExecutionListener.class)
。一些其他的注解或配置也可以神奇地帮你完成这个任务。请查看文档 )) - gavenkoa我曾遇到类似的问题,通过混合使用方法解决了这个问题。我发现这种方法更加有用和可重复使用。我为测试创建了一个Spring配置文件,并编写了一个配置类,在其中以非常简单的方式覆盖要模拟的bean:
@Profile("test")
@Configuration
@Import(ApplicationConfiguration.class)
public class ConfigurationTests {
@MockBean
private Producer kafkaProducer;
@MockBean
private SlackNotifier slackNotifier;
}
从Spring Boot 1.4.0开始,测试时不需要显式指定@Configuration
注解,只需添加一个静态嵌套类并使用@TestConfiguration
进行注释,并提供替代的@Bean
注解和@Primary
注解。
@TestConfiguration
将被添加到主要的Spring Boot测试上下文中(这意味着您的生产bean仍将被创建),但会使用@Primary
注解的@TestConfiguration
中的bean,而非生产bean。
@Import(MyTest.TestConfig.class)
。工厂方法的名称需要与生产配置中的不同(例如 @Configuration @Bean thing(); @TestConfiguration @Primary @Bean thingMock();
)。 - salomvary为了在不同的上下文中使用不同类型的bean,您应该使用Spring配置文件。
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
@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文件。这里有一个例子here。
更新:我不得不添加primary="true"
,显然是必需的。