java - 带有测试 application.properties 的 Junit 5
问题描述
我正在学习 Junit 5 和测试用例。我正在使用 Spring Boot 版本 '2.2.6.RELEASE 和 JUnit 5,在我的应用程序中,我有一个基于属性文件中的布尔标志进行处理的方法。
\src\main\resources\application.properties
#data base connection properties
spring.app.datasource.url=jdbc:mysql://localhost:3306/student_db
spring.app.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.app.datasource.username=root
spring.datasource.password=root
spring.app.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
#additional properties
spring.property.name=shrikant
spring.property.enable=false
数据库连接属性用于创建数据库连接
数据源.java
@Value("${spring.app.datasource.url}")
private String url;
@Value("${spring.app.datasource.driver-class-name}")
private String className;
@Value("${spring.app.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.app.jpa.properties.hibernate.dialect}")
private String dialect;
控制器类
@RestController
public class Controller {
@Value("${spring.property.name}")
private String name;
@Value("${spring.property.enable}")
private boolean status;
public void validateObject(String surName) {
if (status) { # if this flag is true then only process
System.out.println("name= " + name);
System.out.println("surName= " + surName);
}
}
控制器测试.java
@SpringBootTest
class ControllerTest {
@Autowired
private Controller controller;
@Test
void show() {
controller.validateObject("sharma");
}
默认情况下,该标志为 false,因此每次测试用例运行时它都不会处理该对象。所以我尝试在测试文件夹中创建 aplication.properties
\src\test\resources\application.properties
spring.property.name=vishal
spring.property.enable=true
但现在它给了我一个错误
Could not resolve placeholder 'spring.app.datasource.url'
但我不想提供数据库连接 URL,我在测试时没有连接到数据库。
Q1 - 如何仅更改测试用例的属性文件的值。
Q2 - 是否必须提供 \src\main\resources\application.properties 的所有键是 \src\test\resources\application.properties?
我是测试用例的新手,所以很少有解释的答案会受到欢迎。
更新:-我发现
@SpringBootTest
@TestPropertySource(properties = {"spring.property.name=vishal", " spring.property.status=true"})
class ControllerTest {
将通过提供键和值来暂时解决问题,但是我有很多键,无法以这种方式提供。
解决方案
如果您使用@SpringBootTest
,那么您的测试将加载整个 Spring 上下文。这意味着它将创建您所有的 bean 并尝试将它们连接在一起。如果将属性值注入到 bean,则必须为此类测试指定它们,否则,您将无法启动应用程序。
在这种情况下可能对您有所帮助的是使用测试注释,例如@WebMvcTest
或@DataJpaTest
专注于测试应用程序的片段。使用@WebMvcTest
您将获得一个应用程序上下文,其中仅包含控制器以及与您的 Web 层相关的所有内容。其他 bean(如服务类)可以用@MockedBean
.
接下来,为了测试服务类中的业务逻辑,尽量不要使用@SpringBootTest
普通的 JUnit 5 和 Mockito 来验证您的代码。
您可能仍然希望进行一些集成测试,@SpringBootTest
以确保一切正常工作。在这种情况下,您可以在内部或使用注释中硬编码任何静态属性application.properties
,就像您已经做过的那样: .src/test/resources/
@TestPropertySource(properties = {"spring.property.name=vishal", " spring.property.status=true"})
在提供数据库时,您可以配置嵌入式数据库(我会尽量避免)或使用与生产中相同的数据库。在为您的测试提供外部基础设施(如数据库)时,Testcontainers可以为您提供很多帮助。
Spring Boot >= 2.2.6 和 JUnit 的示例设置可能如下所示:
@Testcontainers
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationIT {
@Container
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer()
.withPassword("password")
.withUsername("username");
@DynamicPropertySource
static void postgresqlProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
@Test
public void contextLoads() {
}
}
推荐阅读
- regex - 在 Rust 中将正则表达式捕获转换为 HashMap?
- scala - 重命名嵌套 Spark DataFrame Schema (Scala) 中的键
- python - 考虑到同质到异质的转换,我们能否将 2 个或更多单应矩阵相乘得到另一个?
- angular - 如何使用其他表单元素上传数据
- javascript - 高效的 HTML 工具提示渲染(重用工具提示)
- groovy - 使用 Groovy 修剪视图标准中的绑定变量
- bash - 为什么使用通配符将参数数量减半会因“参数列表太长”而失败?
- json - 如何从 JSON 文件中导入字段?
- html - 如何在网格中放置重叠两行的图像
- mysql - Laravel 和 SQL 类型的良好实践