Spring 通过配置文件使用 yaml 属性启动测试

Spring Boot test with yaml properties by profile

所以这个主题有很多点击率,但其中 none 对我有用。

我有一个非常简单的配置class:

@Configuration
@ConfigurationProperties(prefix = "props")
public class TagIncluder {

    private static final String PARAMETER_NAME = "tags";

    private List<String> tags;

    public TagIncluder() {
        tags = new ArrayList<>();
    }

    public List<String> getTags() {
        return tags;
    }

    @Handler
    public void attachIncludedTags(Exchange exchange) {
        exchange.getIn().setHeader(PARAMETER_NAME, tags);
    }
}

我希望这个 class 能够加载不同的 属性 文件。我正在使用 yaml,我的文件名为 application-tag_test.yml。我曾尝试将此文件放在 src/main/resourcessrc/test/resourcessrc/test/resources/config 中,但从未被拾取。

这是 属性 文件的内容:

props:
  tags:
    - test 

最后,测试用例:

@SpringBootTest
@ActiveProfiles("tag_test")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TagIncluder.class)
public class TagIncluderTest extends ExchangeTestSupport {

    @Autowired
    private TagIncluder sut;

    @Test
    public void attachIncludedTags_shouldUseTagsInFileIfFileSpecified() {
        Exchange testExchange = createExchange();
        sut.attachIncludedTags(testExchange);

        Assertions.assertThat(testExchange.getIn().getHeader("tags", List.class))
            .size().isGreaterThanOrEqualTo(1);
    }
}

此外,我尝试在上述位置放置一个 application.properties 文件,内容如下:

spring.profiles.active=tag_test

Spring 需要什么才能将我的 yaml 文件设置为我正在测试的测试 class 所需的配置?

更新

所以经过一番摸索和反复试验,我发现以下工作:

@SpringBootTest
@ActiveProfiles("tag_test")
@RunWith(SpringJUnit4ClassRunner.class)
public class TagIncluderTest extends ExchangeTestSupport {

    @Autowired
    private TagIncluder sut;

    @Test
    public void attachIncludedTags_shouldUseTagsInFileIfFileSpecified() {
        Exchange testExchange = createExchange();
        sut.attachIncludedTags(testExchange);

        Assertions.assertThat(testExchange.getIn().getHeader("tags", List.class))
            .size().isGreaterThanOrEqualTo(1);
    }
}

这里的不同之处在于我删除了 @ContextConfiguration 注释并让 Spring 处理所有这些。

慢很多,我更愿意指定需要什么。我认为这可能会在未来中断,例如,如果我添加另一个配置 class 将从整个上下文开始并抛出错误,因为这些属性不包含在我的 application-tag_test.yml 配置中。

最后,我尝试配置的上述任何位置都对上述注释有效。不需要指定配置文件的 application.properties

如果有人知道一种方法来指定 什么 应该加载到上下文中,我将非常感谢另一个解决方案。

Spring 启动测试文档指出

External properties, logging, and other features of Spring Boot are installed in the context by default only if you use SpringApplication to create it.

这意味着您需要有一个可用的 Spring 引导应用程序,以便测试与 属性 在测试用例中加载相关的任何内容。

此外,从属性设置列表需要 setter。这有效:

@Configuration
@ConfigurationProperties(prefix = "props")
public class TagIncluder {
    private List<String> tags;

    public void setTags(List<String> tags) {
        this.tags = tags;
    }

    public List<String> getTags() {
        return tags;
    }
}

@Component
public class MyComponent {
    @Autowired
    TagIncluder tagIncluder;
}

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@SpringBootTest
@ActiveProfiles("tag_test")
@RunWith(SpringRunner.class)
public class TagIncluderTest {

    @Autowired
    private TagIncluder sut;

    @Test
    public void attachIncludedTags_shouldUseTagsInFileIfFileSpecified() {
        System.out.println(sut.getTags());
    }
}

在 Jans 上面建议的一些指导下,我已经成功地将测试隔离成一个片段。自动配置测试是关于 here 的,但是它只涉及 Spring 预定义的 @..Test 注释。

例如,如果您深入研究 @WebMvcTest,您会发现 @ImportAutoConfiguration 注释。

使用它,我们可以告诉我们的测试 class 为我们的应用程序的单个 slice 启用自动配置。提供教程 here. The full list of factories available for auto configuration can be found in the spring-boot repository

最后,这是整个测试class:

@ActiveProfiles("tag_test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TagIncluder.class)
@ImportAutoConfiguration(classes = ConfigurationPropertiesAutoConfiguration.class)
public class TagIncluderTest extends ExchangeTestSupport {

    @Autowired
    private TagIncluder sut;

    @Test
    public void attachIncludedTags_shouldUseTagsInFileIfFileSpecified() {
        Exchange testExchange = createExchange();
        sut.attachIncludedTags(testExchange);

        Assertions.assertThat(testExchange.getIn().getHeader("tags", List.class))
            .size().isGreaterThanOrEqualTo(1);
    }
}

测试中的 class 未受影响。

现在我们可以:

  • 使用配置文件
  • 使用 yaml
  • 在Spring上下文
  • 中只测试我们想要的class

这很有启发:)