运行Spring Boot测试的推荐方法是什么,其中在上下文中仅配置了一个测试对象。</ p>
如果我用
注释测试@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
@ContextConfiguration(classes = MyTestBean.class)
然后它似乎可以工作-测试通过,上下文快速启动,并且似乎仅包含我想要的bean。但是,这似乎是对@ContextConfiguration(classes = MyTestBean.class)
注释的不正确使用。如果我正确理解了我所引用的类,那么该类应该是Configuration
类,而不是常规的spring service bean或组件。
是吗?还是这确实是实现此目标的有效方法?我知道还有更复杂的示例,例如org.springframework.boot.test.autoconfigure.json.JsonTest
,它们使用@TypeExcludeFilters(JsonExcludeFilter.class)
来控制上下文-但这对于我的用例来说似乎有些过头了。我只想要一个bean的上下文。
我知道我可以将我正在测试的一个bean构造为POJO,而无需进行弹簧上下文测试,并删除上面的三个注释。但是在我的确切用例中,我实际上依赖于application-test.properties
文件中的设置应用于上下文的某些配置-这就是为什么我使用配置文件集对此进行了Spring Boot测试。从我的角度来看,这不是隔离Spring上下文配置的单个类的普通单元测试-该测试依赖于所应用的某些配置(当前由Spring Boot应用程序属性提供)。我确实可以通过在spring上下文之外创建一个新实例来测试作为POJO的组件,我正在使用构造函数注入,使提供必要的依赖关系变得简单,但是测试确实依赖于日志级别(测试实际上使对正在生成的某些日志进行断言),这要求正确设置日志级别(当前是通过设置弹簧上下文的属性文件中的logging.level.com.example=DEBUG
完成的。)
答案 0 :(得分:3)
在单元测试中仅测试单个类绝对是合理且正常的事情。
在测试上下文中仅包含一个bean是没有问题的。实际上,@Configuration
(通常)只是bean的集合。假设您可以仅使用@Configuration
创建一个MyTestBean
类,但这实际上是不必要的,因为您可以完成使用@ContextConfiguration#classes
列出上下文bean的相同操作。
但是,我确实要指出,仅在真正的单元测试中测试单个bean,最佳实践理想地倾向于通过构造函数设置bean并以这种方式测试类。这是Spring员工推荐使用构造函数与属性注入的关键原因。有关更多信息,请参见标题为基于构造函数或基于setter的DI 的部分。of this article,Oliver Gierke's comment(即Spring Data项目的负责人)和google。这可能是您对设置一个bean的上下文感到奇怪的原因!
答案 1 :(得分:1)
对于初学者来说,由于它已经回答了您的问题,因此建议您首先阅读文档(例如,此答案下面的JavaDoc链接)。
如果我正确理解了我所引用的课程,那应该是
Configuration
类,而不是常规的spring service bean或 组件。对吗?
不,那不是完全正确。
提供给@ContextConfiguration
的类通常是 @Configuration
类,但这不是必需的。
以下是JavaDoc for @ContextConfiguration
的摘录:
带注释的类
带注释的类可以指代以下任何一个。
- 用
@Configuration
注释的类- 组件(即用
@Component
,@Service
,@Repository
等注释的类)- 一个兼容JSR-330的类,带有
javax.inject
批注- 包含
@Bean
方法的其他任何类
因此,您可以将任何“带注释的类”传递给@ContextConfiguration
。
或者这确实是实现此目标的有效方法吗?
实际上,这是实现该目标的有效方法;但是,加载包含单个用户bean的ApplicationContext
也有点不寻常。
此致
Sam(Spring TestContext Framework的作者)
答案 2 :(得分:0)
您还可以使用ApplicationContextRunner
使用您选择的测试配置来创建上下文(如果您愿意,可以将事件与一个bean一起使用,但是正如其他人已经提到的那样,对于一个bean,它更有可能存在构造函数的经典方式而无需使用任何弹簧魔术)。
我喜欢这种测试方式的事实是测试运行非常快,因为您没有加载所有上下文。当被测试的bean没有其他自动连接的依赖关系时,最好使用此方法,而更方便使用@SpringBootTest
。
下面的示例说明了使用它来实现目标的方式:
class MyTest {
@Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
@Configuraiton
public static class TestConfiguration {
@Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}