英文:
how to create a Mock database and add data in mock db for integration testing using postgres db and java
问题
我想进行集成测试,为此我想创建一个测试数据库并添加一些数据。
在进行集成测试时,我应该如何指向测试数据库?
感谢您的帮助......
英文:
I want to perform the Integration test for which I want to create a test DB and add some data.
how should I point to the test DB while doing an integration test?
Thanks for Help......
答案1
得分: 2
以下是翻译好的部分:
你可以使用 testcontainers 来实现这个。你可以观看这个 视频 来了解关于这个的想法,以及如何在你的 Spring Boot 应用程序中配置它。
对于你的 Spring 集成测试,创建一个如下所示的配置:
AbstractIT.java
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"spring.main.allow-bean-definition-overriding=true"})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // 不要用内存数据库替换我们的数据库
@ContextConfiguration(initializers = AbstractIT.DockerPostgresDataSourceInitializer.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public abstract class AbstractIT {
private static PostgreSQLContainer<?> postgresDBContainer = new PostgreSQLContainer<>("postgres:9.6")
.withUrlParam("TC_DAEMON", "true")
.withFileSystemBind("docker/db", "/docker-entrypoint-initdb.d", BindMode.READ_WRITE);
static {
postgresDBContainer.start();
}
public static class DockerPostgresDataSourceInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
Assertions.assertNotNull(applicationContext);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
applicationContext,
"spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true",
"spring.datasource.driver-class-name=" + postgresDBContainer.getDriverClassName(),
"spring.datasource.url=" + postgresDBContainer.getJdbcUrl(),
"spring.datasource.username=" + postgresDBContainer.getUsername(),
"spring.datasource.password=" + postgresDBContainer.getPassword()
);
}
}
}
现在你可以按照下面的示例,在你的集成测试中编写代码:
UserControllerIT.java
class UserControllerIT extends AbstractIT {
@Autowired
private TestRestTemplate template;
@Autowired
private UserRepository userRepository;
@Test
@Order(1)
@DisplayName("测试获取所有用户详情")
void getAllUsersTest() {
ResponseEntity<List<UserDTO>> response = this.template.exchange("/v1/users", GET, HttpEntity.EMPTY, new ParameterizedTypeReference<List<UserDTO>>() {
});
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody())
.isNotEmpty()
.hasSize(3)
.extracting(UserDTO::getEmail).containsAnyOf("user1@some.com");
}
// 其他测试方法的翻译...
private UserDTO buildUserRequest() {
return UserDTO.builder()
.email("user4@some.com")
.lastName("Maria")
.firstName("Fernandes")
.build();
}
private Map<String, String> singleParam(String key, String value) {
Map<String, String> params = new HashMap<>();
params.put(key, value);
return params;
}
}
你可以在这个 Github 仓库中找到完整的运行中应用程序 - https://github.com/nidhishkrishnan/stackoverflow/tree/master/employee-testcontainer
英文:
You can use testcontainers for achieving this. You can watch this video to get an idea about this and how to configure it in your spring boot application
For your spring integration test create a configuration like as shown below
AbstractIT.java
@Testcontainers
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"spring.main.allow-bean-definition-overriding=true"})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // don't replace our DB with an in-memory one
@ContextConfiguration(initializers = AbstractIT.DockerPostgresDataSourceInitializer.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public abstract class AbstractIT {
private static PostgreSQLContainer<?> postgresDBContainer = new PostgreSQLContainer<>("postgres:9.6")
.withUrlParam("TC_DAEMON", "true")
.withFileSystemBind("docker/db", "/docker-entrypoint-initdb.d", BindMode.READ_WRITE);
static {
postgresDBContainer.start();
}
public static class DockerPostgresDataSourceInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
Assertions.assertNotNull(applicationContext);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
applicationContext,
"spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true",
"spring.datasource.driver-class-name="+postgresDBContainer.getDriverClassName(),
"spring.datasource.url=" + postgresDBContainer.getJdbcUrl(),
"spring.datasource.username=" + postgresDBContainer.getUsername(),
"spring.datasource.password=" + postgresDBContainer.getPassword()
);
}
}
}
Now you can write your Integration test like as shown in the below sample example
UserControllerIT.java
class UserControllerIT extends AbstractIT {
@Autowired
private TestRestTemplate template;
@Autowired
private UserRepository userRepository;
@Test
@Order(1)
@DisplayName("Testing to get all the user details")
void getAllUsersTest() {
ResponseEntity<List<UserDTO>> response = this.template.exchange("/v1/users", GET, HttpEntity.EMPTY, new ParameterizedTypeReference<List<UserDTO>>() {
});
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody())
.isNotEmpty()
.hasSize(3)
.extracting(UserDTO::getEmail).containsAnyOf("user1@some.com");
}
@Test
@Order(2)
@DisplayName("Testing for saving user details")
void saveUsersTest() {
ResponseEntity<Void> response = this.template.postForEntity("/v1/users", new HttpEntity<>(buildUserRequest()), Void.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
long usersCount = userRepository.count();
assertThat(usersCount).isEqualTo(4);
}
@Test
@Order(3)
@DisplayName("Testing to deleting user details by id")
void deleteUsersTest() {
this.template.delete("/v1/users/{id}", singleParam("id", "21"));
boolean userExists = userRepository.existsById(21L);
assertThat(userExists).isFalse();
}
@Test
@Order(4)
@DisplayName("Testing to finding user details by id")
void findUserByIdTest() {
ResponseEntity<UserDTO> response = this.template.getForEntity("/v1/users/{id}", UserDTO.class, singleParam("id", "22"));
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody())
.extracting(UserDTO::getEmail, UserDTO::getFirstName, UserDTO::getLastName)
.containsExactly("user2@some.com", "John", "Duke");
}
private UserDTO buildUserRequest() {
return UserDTO.builder()
.email("user4@some.com")
.lastName("Maria")
.firstName("Fernandes")
.build();
}
private Map<String, String> singleParam(String key, String value) {
Map<String, String> params = new HashMap<>();
params.put(key, value);
return params;
}
}
You can see the full running application under this Github Repo - https://github.com/nidhishkrishnan/stackoverflow/tree/master/employee-testcontainer
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论