仅使用一个Bean进行Spring Context测试

时间:2018-06-26 22:08:09

标签: spring-boot spring-test spring-boot-test

运行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完成的。)

3 个答案:

答案 0 :(得分:3)

在单元测试中仅测试单个类绝对是合理且正常的事情。

在测试上下文中仅包含一个bean是没有问题的。实际上,@Configuration(通常)只是bean的集合。假设您可以仅使用@Configuration创建一个MyTestBean类,但这实际上是不必要的,因为您可以完成使用@ContextConfiguration#classes列出上下文bean的相同操作。

但是,我确实要指出,仅在真正的单元测试中测试单个bean,最佳实践理想地倾向于通过构造函数设置bean并以这种方式测试类。这是Spring员工推荐使用构造函数与属性注入的关键原因。有关更多信息,请参见标题为基于构造函数或基于setter的DI 的部分。of this articleOliver 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();
    }
  }
}