오픈소스
[TestContainers] 스프링부트에서 TestContainer 사용해보기
ntne
2024. 4. 20. 22:27
실행환경
Java 17
Intellij IDEA
Gradle
Docker Desktop
1. Gradle 추가 (JPA, PostgreSQL, JUnit)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
}
2. Customer.java 엔티티 생성
package com.testcontainers.demo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "customers")
class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
public Customer() {}
public Customer(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
3. JPA repository 생성
package com.testcontainers.demo;
import org.springframework.data.jpa.repository.JpaRepository;
interface CustomerRepository extends JpaRepository<Customer, Long> {}
4. DB 스키마 생성
create table if not exists customers (
id bigserial not null,
name varchar not null,
email varchar not null,
primary key (id),
UNIQUE (email)
);
application.properties 변경
spring.sql.init.mode=always
5. REST API Endpoint 생성
package com.testcontainers.demo;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
class CustomerController {
private final CustomerRepository repo;
CustomerController(CustomerRepository repo) {
this.repo = repo;
}
@GetMapping("/api/customers")
List<Customer> getAll() {
return repo.findAll();
}
}
6. API Endpoint 테스트 작성
build.gradle 추가
testImplementation 'io.rest-assured:rest-assured'
CustomerControllerTest 생성
package com.testcontainers.demo;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasSize;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.List;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class CustomerControllerTest {
@LocalServerPort
private Integer port;
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(
"postgres:15-alpine"
);
@BeforeAll
static void beforeAll() {
postgres.start();
}
@AfterAll
static void afterAll() {
postgres.stop();
}
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
CustomerRepository customerRepository;
@BeforeEach
void setUp() {
RestAssured.baseURI = "http://localhost:" + port;
customerRepository.deleteAll();
}
@Test
void shouldGetAllCustomers() {
List<Customer> customers = List.of(
new Customer(null, "John", "john@mail.com"),
new Customer(null, "Dennis", "dennis@mail.com")
);
customerRepository.saveAll(customers);
given()
.contentType(ContentType.JSON)
.when()
.get("/api/customers")
.then()
.statusCode(200)
.body(".", hasSize(2));
}
}
7. 테스트
* Docker Desktop 띄우고 테스트