Rol*_*der 5 junit spring spring-test spring-boot
我使用 spring-boot-starter-web 和 spring-boot-starter-test。
假设我有一个用于绑定配置属性的类:
@ConfigurationProperties(prefix = "dummy")
public class DummyProperties {
@URL
private String url;
// getter, setter ...
}
Run Code Online (Sandbox Code Playgroud)
现在我想测试我的 bean 验证是否正确。如果该属性dummy.value未设置或包含无效 URL ,则上下文应该无法启动(带有特定错误消息)。如果属性包含有效的 URL,则上下文应该开始。(测试将显示@NotNull缺少。)
一个测试类看起来像这样:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@IntegrationTest({ "dummy.url=123:456" })
public class InvalidUrlTest {
// my test code
}
Run Code Online (Sandbox Code Playgroud)
此测试将失败,因为提供的属性无效。告诉 Spring/JUnit 的最佳方式是什么:“是的,这个错误是意料之中的”。在普通的 JUnit 测试中,我会使用 ExpectedException。
ApplicationContextRunner它在 Spring Boot 参考文档中有描述:https :
//docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html#boot-features-test-autoconfig
有一个关于它的快速指南:https :
//www.baeldung.com/spring-boot-context-runner
private static final String POSITIVE_CASE_CONFIG_FILE =
"classpath:some/path/positive-case-config.yml";
private static final String NEGATIVE_CASE_CONFIG_FILE =
"classpath:some/path/negative-case-config.yml";
@Test
void positiveTest() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withInitializer(new ConfigDataApplicationContextInitializer())//1
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.DEBUG))//2
.withUserConfiguration(MockBeansTestConfiguration.class)//3
.withPropertyValues("spring.config.location=" + POSITIVE_CASE_CONFIG_FILE)//4
.withConfiguration(AutoConfigurations.of(BookService.class));//5
contextRunner
.run((context) -> {
Assertions.assertThat(context).hasNotFailed();//6
});
}
@Test
void negativeTest() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withInitializer(new ConfigDataApplicationContextInitializer())//1
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.DEBUG))//2
.withUserConfiguration(MockBeansTestConfiguration.class)//3
.withPropertyValues("spring.config.location=" + NEGATIVE_CASE_CONFIG_FILE)//4
.withConfiguration(AutoConfigurations.of(BookService.class));//5
contextRunner
.run((context) -> {
assertThat(context)
.hasFailed();
assertThat(context.getStartupFailure())
.isNotNull();
assertThat(context.getStartupFailure().getMessage())
.contains("Some exception message");
assertThat(extractFailureCauseMessages(context))
.contains("Cause exception message");
});
}
private List<String> extractFailureCauseMessages(AssertableApplicationContext context) {
var failureCauseMessages = new ArrayList<String>();
var currentCause = context.getStartupFailure().getCause();
while (!Objects.isNull(currentCause)) {//7
failureCauseMessages.add(currentCause.getMessage());
currentCause = currentCause.getCause();
}
return failureCauseMessages;
}
Run Code Online (Sandbox Code Playgroud)
Junit5 Spring Boot Test Annotations中类似定义的示例说明:
application.properties或application.ymlConditionEvaluationReport使用给定的日志级别时,应用程序上下文失败@Autowired BookRepository我们的BookService,我们提供模拟BookRepository的MockBeansTestConfiguration。类似于@Import({MockBeansTestConfiguration.class})在测试类中和@TestConfiguration在普通 Junit5 Spring Boot 测试中使用模拟 bean 的类@TestPropertySource(properties = { "spring.config.location=" + POSITIVE_CASE_CONFIG_FILE})@ContextConfiguration(classes = {BookService.class})或@SpringBootTest(classes = {BookService.class})一起使用@Import({BookService.class})Assertions.assertThat,但我想展示这个方法的来源Objects.isNull,但我想展示这个方法的来源MockBeansTestConfiguration 类:
@TestConfiguration
public class MockBeansTestConfiguration {
private static final Book SAMPLE_BOOK = Book.of(1L, "Stanis?aw Lem", "Solaris", "978-3-16-148410-0");
@Bean
public BookRepository mockBookRepository() {
var bookRepository = Mockito.mock(BookRepository.class);//1
Mockito.when(bookRepository.findByIsbn(SAMPLE_BOOK.getIsbn()))//2
.thenReturn(SAMPLE_BOOK);
return bookRepository;
}
}
Run Code Online (Sandbox Code Playgroud)
备注:
1,2。应该有静态导入,但我想展示这个方法的来源
为什么首先要进行集成测试?为什么要为此启动一个完整的 Spring Boot 应用程序?
对我来说这看起来像是单元测试。话虽如此,您有多种选择:
@IntegrationTest,Spring Boot 将不会启动 Web 服务器(使用@PropertySource将值传递给您的测试,但将无效值传递给整个测试类感觉是错误的)spring.main.web-environment=false禁用网络服务器(但考虑到上面的观点,这是愚蠢的)DummyProperties您的单元测试。您甚至不需要为此启动 Spring Boot 应用程序。看看我们自己的测试套件我肯定会选择最后一个。也许您有充分的理由为此进行集成测试?
| 归档时间: |
|
| 查看次数: |
4221 次 |
| 最近记录: |