Spring 仅使用一个 Bean 进行上下文测试
Spring Context Test With Just One Bean
运行 spring 启动测试的推荐方法是什么,其中只有一个被测对象在上下文中配置。
如果我用
注释测试
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
@ContextConfiguration(classes = MyTestBean.class)
然后它似乎工作了 - 测试通过,上下文快速启动并且似乎只包含我想要的 bean。但是,这似乎是对 @ContextConfiguration(classes = MyTestBean.class)
注释的错误使用。如果我理解正确,我引用的 class 应该是 Configuration
class,而不是常规的 spring 服务 bean 或组件。
是吗?或者这确实是实现此目标的有效方法?我知道有更复杂的示例,例如 org.springframework.boot.test.autoconfigure.json.JsonTest
,它们使用 @TypeExcludeFilters(JsonExcludeFilter.class)
来控制上下文——但这对于我的用例来说似乎有点过分了。我只想要我的一个 bean 的上下文。
澄清
我知道我可以在没有 spring 上下文测试的情况下将我正在测试的一个 bean 构建为 POJO,并删除上面的三个注释。但在我的精确用例中,我实际上依赖于 application-test.properties
文件中的设置应用于上下文的一些配置 - 这就是为什么我将其设为 Spring 带有配置文件集的启动测试.从我的角度来看,这不是孤立于 spring 上下文配置的单个 class 的普通单元测试 - 该测试依赖于所应用的某些配置(目前由 spring 启动应用程序属性)。我确实可以通过在 spring 上下文之外创建一个新实例来将组件作为 POJO 进行测试,我正在使用构造函数注入来简化必要依赖项的提供,但测试确实依赖于诸如日志级别之类的东西(该测试实际上对正在生成的某些日志做出断言),这需要正确设置日志级别(目前正在通过设置 spring 上下文的属性文件中的 logging.level.com.example=DEBUG
完成)。
在单元测试中只测试一个class绝对是合理和正常的事情。
在您的测试上下文中只包含一个 bean 是没有问题的。实际上,@Configuration
(通常)只是 collection 个 bean。您可以假设只使用 MyTestBean
创建一个 @Configuration
class,但这实际上是不必要的,因为您可以完成使用 @ContextConfiguration#classes
列出上下文 bean 的相同操作。 =15=]
但是,我确实想指出,对于在真正的单元测试中仅测试单个 bean,最佳实践理想地倾向于通过构造函数设置 bean 并以这种方式测试 class。这是 Spring 人推荐使用构造函数而不是 属性 注入的一个关键原因。有关详细信息,请参阅标题为 Constructor-based 或 setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google 的部分。这可能是您对为一个 bean 设置上下文感到奇怪的原因!
对于初学者来说,首先阅读文档(例如,此答案下方链接的 JavaDoc)是推荐的最佳做法,因为它已经回答了您的问题。
If I understand correctly the class that I reference is supposed to be
a Configuration
class, not a regular spring service bean or
component for example.
Is that right?
不,这不完全正确。
类 提供给 @ContextConfiguration
通常 @Configuration
类,但这不是必需的。
以下是 JavaDoc for @ContextConfiguration
的摘录:
Annotated Classes
The term annotated class can refer to any of the following.
- A class annotated with
@Configuration
- A component (i.e., a class annotated with
@Component
, @Service
, @Repository
, etc.)
- A JSR-330 compliant class that is annotated with
javax.inject
annotations
- Any other class that contains
@Bean
-methods
因此您可以将任何 "annotated class" 传递给 @ContextConfiguration
。
Or is this indeed a valid way to achieve this goal?
事实上,这是实现该目标的有效方法;但是,加载包含单个用户 bean 的 ApplicationContext
也有点不寻常。
此致,
Sam(Spring TestContext Framework 的作者)
您还可以使用 ApplicationContextRunner
使用您选择的测试配置创建上下文(如果您愿意,甚至可以使用一个 bean,但正如其他人已经提到的一个 bean在不使用任何 spring 魔法 的情况下以经典方式使用构造函数更合理)。
我喜欢这种测试方式的原因是测试 运行 非常快,因为您不需要加载所有上下文。这种方法最好在被测bean没有任何Autowired依赖时使用,否则使用@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();
}
}
}
运行 spring 启动测试的推荐方法是什么,其中只有一个被测对象在上下文中配置。
如果我用
注释测试@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.profiles.active=test")
@ContextConfiguration(classes = MyTestBean.class)
然后它似乎工作了 - 测试通过,上下文快速启动并且似乎只包含我想要的 bean。但是,这似乎是对 @ContextConfiguration(classes = MyTestBean.class)
注释的错误使用。如果我理解正确,我引用的 class 应该是 Configuration
class,而不是常规的 spring 服务 bean 或组件。
是吗?或者这确实是实现此目标的有效方法?我知道有更复杂的示例,例如 org.springframework.boot.test.autoconfigure.json.JsonTest
,它们使用 @TypeExcludeFilters(JsonExcludeFilter.class)
来控制上下文——但这对于我的用例来说似乎有点过分了。我只想要我的一个 bean 的上下文。
澄清
我知道我可以在没有 spring 上下文测试的情况下将我正在测试的一个 bean 构建为 POJO,并删除上面的三个注释。但在我的精确用例中,我实际上依赖于 application-test.properties
文件中的设置应用于上下文的一些配置 - 这就是为什么我将其设为 Spring 带有配置文件集的启动测试.从我的角度来看,这不是孤立于 spring 上下文配置的单个 class 的普通单元测试 - 该测试依赖于所应用的某些配置(目前由 spring 启动应用程序属性)。我确实可以通过在 spring 上下文之外创建一个新实例来将组件作为 POJO 进行测试,我正在使用构造函数注入来简化必要依赖项的提供,但测试确实依赖于诸如日志级别之类的东西(该测试实际上对正在生成的某些日志做出断言),这需要正确设置日志级别(目前正在通过设置 spring 上下文的属性文件中的 logging.level.com.example=DEBUG
完成)。
在单元测试中只测试一个class绝对是合理和正常的事情。
在您的测试上下文中只包含一个 bean 是没有问题的。实际上,@Configuration
(通常)只是 collection 个 bean。您可以假设只使用 MyTestBean
创建一个 @Configuration
class,但这实际上是不必要的,因为您可以完成使用 @ContextConfiguration#classes
列出上下文 bean 的相同操作。 =15=]
但是,我确实想指出,对于在真正的单元测试中仅测试单个 bean,最佳实践理想地倾向于通过构造函数设置 bean 并以这种方式测试 class。这是 Spring 人推荐使用构造函数而不是 属性 注入的一个关键原因。有关详细信息,请参阅标题为 Constructor-based 或 setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google 的部分。这可能是您对为一个 bean 设置上下文感到奇怪的原因!
对于初学者来说,首先阅读文档(例如,此答案下方链接的 JavaDoc)是推荐的最佳做法,因为它已经回答了您的问题。
If I understand correctly the class that I reference is supposed to be a
Configuration
class, not a regular spring service bean or component for example.Is that right?
不,这不完全正确。
类 提供给 @ContextConfiguration
通常 @Configuration
类,但这不是必需的。
以下是 JavaDoc for @ContextConfiguration
的摘录:
Annotated Classes
The term annotated class can refer to any of the following.
- A class annotated with
@Configuration
- A component (i.e., a class annotated with
@Component
,@Service
,@Repository
, etc.)- A JSR-330 compliant class that is annotated with
javax.inject
annotations- Any other class that contains
@Bean
-methods
因此您可以将任何 "annotated class" 传递给 @ContextConfiguration
。
Or is this indeed a valid way to achieve this goal?
事实上,这是实现该目标的有效方法;但是,加载包含单个用户 bean 的 ApplicationContext
也有点不寻常。
此致,
Sam(Spring TestContext Framework 的作者)
您还可以使用 ApplicationContextRunner
使用您选择的测试配置创建上下文(如果您愿意,甚至可以使用一个 bean,但正如其他人已经提到的一个 bean在不使用任何 spring 魔法 的情况下以经典方式使用构造函数更合理)。
我喜欢这种测试方式的原因是测试 运行 非常快,因为您不需要加载所有上下文。这种方法最好在被测bean没有任何Autowired依赖时使用,否则使用@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();
}
}
}