【问题标题】:Spring Boot properties in 'application.yml' not loading from JUnit Test'application.yml' 中的 Spring Boot 属性未从 JUnit 测试加载
【发布时间】:2023-04-10 06:39:01
【问题描述】:

我做错了什么?我正在使用这个运行并找到我的src/main/resources/config/application.yml 的小型独立应用程序。相同的配置在 JUnit 中不起作用,见下文:

@Configuration
@ComponentScan
@EnableConfigurationProperties

public class TestApplication {

    public static void main(String[] args) {

        SpringApplication.run(TestApplication.class);
    }
}


@Component
@ConfigurationProperties

public class Bean{
    ...
}

以下不起作用,application.yml 中的相同属性未加载,Bean 只有 null 值:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestApplication.class)

public class SomeTestClass {
    ...
}

【问题讨论】:

    标签: java spring junit spring-boot spring-test


    【解决方案1】:

    试试这个:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = TestApplication.class, 
        initializers = ConfigFileApplicationContextInitializer.class)
    public class SomeTestClass {
        ...
    }
    

    编辑

    对于 Spring Boot 版本 1.5+,删除了 SpringApplicationConfiguration 以支持 SpringBootTest 或直接使用 SpringBootContextLoader

    您仍然可以将initializers 参数与ContextConfiguration 注释一起使用。

    【讨论】:

    • 我使用了 \@ContextConfiguration 而不是 \@SpringApplicationConfiguration 并且刚刚添加了 initializers 字段,这也很有效。我的类路径中似乎没有 SpringApplicationConfiguration。
    • @k-den,您可能已经在使用 Spring Boot 1.5.x,其中 SpringApplicationConfiguration 已被删除(自 1.4.x 起已弃用)。
    【解决方案2】:

    使用 @SpringBootTest 在 SpringBoot 2.0 中加载 any 自定义 yml 文件的技巧

    • 在 test\resources 中创建一些 yml 文件
    • 使用ConfigFileApplicationContextInitializerspring.config.location 属性

    示例代码:

    @RunWith(SpringRunner.class)
    @ContextConfiguration(
        classes = { MyConfiguration.class, AnotherDependancy.class },
        initializers = {ConfigFileApplicationContextInitializer.class} )
    @TestPropertySource(properties = { "spring.config.location=classpath:myApp-test.yml" })
    public class ConfigProviderTest {
        @Autowired
        private MyConfiguration myConfiguration; //this will be filled with myApp-test.yml 
    
       @Value("${my.config-yml-string}")
       private String someSrting; //will get value from the yml file.
    
    }
    

    对于 JUnit 5,使用 @ExtendWith(SpringExtension.class) 注释而不是 @RunWith(SpringRunner.class)

    【讨论】:

    • 但是你必须注意一些事情......因为你使用的是@ContextConfiguration,所以这个测试实际上会有一个上下文。因此,下一个测试类将具有相同的上下文,因为 Spring 在测试之间重用它,并且当一直执行时,您的测试类可能会因副作用而失败。为避免这种行为,您还必须使用 @DirtiesContext@ContextConfiguration
    • @AngelPinazo,你是对的,这个例子适用于 hello world 项目中的单个测试执行,但在现实世界中没有用。
    • 对于那些想要真正了解更多关于@DirtiesContext的人
    • 这更适合需要应用程序上下文的集成测试。恕我直言,单元测试永远不需要应用程序上下文(除非它是 spring 本身的单元测试)。无论如何,我一直在寻找集成测试解决方案,所以还是谢谢
    【解决方案3】:

    这是另一种方式:[Spring Boot v1.4.x]

    @Configuration
    @ConfigurationProperties(prefix = "own")
    public class OwnSettings {
    
        private String name;
        Getter & setters...
    
    }
    

    import org.springframework.boot.test.context.SpringBootTestContextBootstrapper;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @BootstrapWith(SpringBootTestContextBootstrapper.class)
    public class OwnSettingsTest {
    
      @Autowired
      private OwnSettings bean;
    
      @Test
      public void test() {
        bean.getName();
      }
    }
    

    仅当“application.properties”文件也存在时才有效。

    例如maven 项目:

    src/main/resources/application.properties [ 文件可以为空,但必须填写! ]
    src/main/resources/application.yml [这是你真正的配置文件]

    【讨论】:

    • 非常感谢!它在 1.4.3.RELEASE 中没有 application.properties 就可以工作。我的资源下只有 application.yml。
    • 不客气 :-) 很高兴知道它现在可以在没有 'application.properties' 的情况下工作。感谢您提供信息。
    • 请问SpringBootTestContextBootstrapper.class 是什么?我在org.springframework.boot:spring-boot:1.5.4.RELEASE没有它
    • 拯救了我的一天!!多谢! @DimitriKopriwa 你可以通过` testCompile("org.springframework.boot:spring-boot-test:${springBootVersion}") ` 添加它
    【解决方案4】:

    2017 年 2 月的替代方案:

    @SpringBootTest
    @ContextConfiguration(classes = { TestApplication.class })
    @RunWith(SpringRunner.class)
    public class SomeTestClass {
       ...
    }
    

    精益变体(没有@SpringBootTest):

    @ContextConfiguration(classes = { TestApplication.class },
                     initializers = { ConfigFileApplicationContextInitializer.class })
    @RunWith(SpringRunner.class)
    public class SomeTestClass {
    

    【讨论】:

    • 但是@SpringBootTest 不会引导你进行单元测试,而是更多的集成测试。
    • 这是真的,但有时我只是想看看属性正在加载。
    • initializers = { ConfigFileApplicationContextInitializer.class } 是我要找的!谢谢。
    【解决方案5】:

    使用 Spring Boot 2 进行单元测试

    spring boot 2 默认支持 'application.properties', 对于 'application.yml' 只需在下面添加:

    @TestPropertySource(properties = { "spring.config.location=classpath:application.yml" })
    

    例如

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @TestPropertySource(properties = { "spring.config.location=classpath:application.yml" })
    public class ServiceTest {...}
    

    【讨论】:

      【解决方案6】:

      Spring boot 2 示例:

      private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
              .withInitializer(new ConfigFileApplicationContextInitializer());
      
      @Test public void test() throws Exception {
      
          this.contextRunner
          .withUserConfiguration(TestApplication.class)
          .run((context) -> {
      
              .....
      
          });
      }
      

      【讨论】:

      • 谢谢,它帮助了我,但在当前的 Spring Boot 版本中,ConfigFileApplicationContextInitializer 已被弃用。我们可以改用ConfigDataApplicationContextInitializer,结果是一样的。所以我们会有private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withInitializer(new ConfigDataApplicationContextInitializer());
      【解决方案7】:

      添加到Liamanswer,替代方案将是:

      @TestPropertySource(locations = { "classpath:application.yaml" })
      

      这里的主要区别在于,如果 application.yaml 不在您的 /test/resources 目录中,则测试将失败并出现文件未找到异常

      【讨论】:

        【解决方案8】:

        在我的情况下,我试图测试一个没有在常规应用程序类路径中声明的 @SpringBootApp 的库,但我的测试上下文中确实有一个。在调试完 Spring Boot 初始化过程后,我发现 Spring Boot 的 YamlPropertySourceLoader(从 1.5.2.RELEASE 开始)不会加载 YAML 属性,除非 org.yaml.snakeyaml.Yaml 在类路径上。我的解决方案是在我的 POM 中添加 snakeyaml 作为测试依赖项:

            <dependency>
                <groupId>org.yaml</groupId>
                <artifactId>snakeyaml</artifactId>
                <version>1.19</version>
                <scope>test</scope>
            </dependency>
        

        【讨论】:

          【解决方案9】:

          扩展Liamanswer

          您可以添加 spring.config.additional-location=classpath:application-overrides.yaml 属性,以便默认位置的配置将与提供的其他配置合并:

          @RunWith(SpringRunner.class)
          @SpringBootTest
          @TestPropertySource(properties = {
            "spring.config.additional-location=classpath:testcases/test-case-properties.yaml",
          })
          public class SpecificTestCaseIntegrationTest {
          

          【讨论】:

            【解决方案10】:

            由于 spring-boot 版本 2.6.0 org.springframework.boot.test.context.ConfigFileApplicationContextInitializer 已弃用,建议使用 org.springframework.boot.test.context.ConfigDataApplicationContextInitializer

            在您的测试中,您可以将其用作:

            @ContextConfiguration(classes = {
              ...        
            }, initializers = ConfigDataApplicationContextInitializer.class)
            public class MyTestingClassIT
            

            【讨论】:

              【解决方案11】:

              这行得通

              import org.junit.Test;
              import org.junit.runner.RunWith;
              import org.springframework.boot.test.context.SpringBootTest;
              import org.springframework.test.context.junit4.SpringRunner;
              
              @RunWith(SpringRunner.class)
              @SpringBootTest
              public class ApplicationTest {
              
                  @Test
                  public void contextLoads() {
                  }
              
              }
              

              【讨论】:

              • 这是我期望的工作,但这不适用于 SpringBoot 1.5+
              猜你喜欢
              • 2019-04-26
              • 2019-11-23
              • 2020-03-07
              • 1970-01-01
              • 2020-10-23
              • 1970-01-01
              • 2019-04-24
              • 1970-01-01
              • 2019-01-30
              相关资源
              最近更新 更多