Skip to content

Commit

Permalink
test: TestContainer 적용 (#27)
Browse files Browse the repository at this point in the history
* test: TestContainer 적용

* test: TestContainer MySQL 버전 5.7로 변경

* test: RestAssured port 선언조건 추가
  • Loading branch information
Choi-JJunho authored Dec 18, 2023
1 parent 3c61882 commit e491214
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 19 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.mysql:mysql-connector-j'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.testcontainers:testcontainers:1.19.3'
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'
testImplementation 'org.testcontainers:mysql'
testImplementation 'io.rest-assured:rest-assured:5.3.2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/application-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spring:
jpa:
hibernate:
ddl-auto: create
58 changes: 58 additions & 0 deletions src/test/java/in/koreatech/koin/AcceptanceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package in.koreatech.koin;

import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

import in.koreatech.koin.support.DBInitializer;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
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.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;

@SpringBootTest(webEnvironment = RANDOM_PORT)
@Import(DBInitializer.class)
@ActiveProfiles("test")
public abstract class AcceptanceTest {

private static final String ROOT = "test";
private static final String ROOT_PASSWORD = "1234";

@LocalServerPort
protected int port;

@Autowired
private DBInitializer dataInitializer;

@Container
protected static MySQLContainer container;

@DynamicPropertySource
private static void configureProperties(final DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", container::getJdbcUrl);
registry.add("spring.datasource.username", () -> ROOT);
registry.add("spring.datasource.password", () -> ROOT_PASSWORD);
}

static {
container = (MySQLContainer) new MySQLContainer("mysql:5.7.34")
.withDatabaseName("test")
.withUsername(ROOT)
.withPassword(ROOT_PASSWORD)
.withCommand("--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci");
container.start();
}

@BeforeEach
void delete() {
if (RestAssured.port == RestAssured.UNDEFINED_PORT) {
RestAssured.port = port;
}
dataInitializer.clear();
}
}
23 changes: 4 additions & 19 deletions src/test/java/in/koreatech/koin/acceptance/TrackApiTest.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package in.koreatech.koin.acceptance;

import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD;

import in.koreatech.koin.AcceptanceTest;
import in.koreatech.koin.domain.Member;
import in.koreatech.koin.domain.TechStack;
import in.koreatech.koin.domain.Track;
Expand All @@ -14,21 +12,12 @@
import io.restassured.response.Response;
import java.time.format.DateTimeFormatter;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
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.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;

@SpringBootTest(webEnvironment = RANDOM_PORT)
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
class TrackApiTest {

@LocalServerPort
int port;
class TrackApiTest extends AcceptanceTest {

@Autowired
private TrackRepository trackRepository;
Expand All @@ -39,11 +28,6 @@ class TrackApiTest {
@Autowired
private MemberRepository memberRepository;

@BeforeEach
void setUp() {
RestAssured.port = port;
}

@Test
@DisplayName("BCSDLab 트랙 정보를 조회한다")
void findTracks() {
Expand Down Expand Up @@ -119,7 +103,8 @@ void findTrack() {
softly.assertThat(response.body().jsonPath().getString("TrackName")).isEqualTo(track.getName());

softly.assertThat(response.body().jsonPath().getList("Members")).hasSize(1);
softly.assertThat(response.body().jsonPath().getInt("Members[0].id")).isEqualTo(member.getId());
softly.assertThat(response.body().jsonPath().getInt("Members[0].id"))
.isEqualTo(member.getId().longValue());
softly.assertThat(response.body().jsonPath().getString("Members[0].name")).isEqualTo(member.getName());
softly.assertThat(response.body().jsonPath().getString("Members[0].student_number"))
.isEqualTo(member.getStudentNumber());
Expand Down
61 changes: 61 additions & 0 deletions src/test/java/in/koreatech/koin/support/DBInitializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package in.koreatech.koin.support;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestComponent;
import org.springframework.transaction.annotation.Transactional;

@TestComponent
public class DBInitializer {

private static final int OFF = 0;
private static final int ON = 1;
private static final int COLUMN_INDEX = 1;

private final List<String> tableNames = new ArrayList<>();

@Autowired
private DataSource dataSource;

@PersistenceContext
private EntityManager entityManager;

private void findDatabaseTableNames() {
try (final Statement statement = dataSource.getConnection().createStatement()) {
ResultSet resultSet = statement.executeQuery("SHOW TABLES");
while (resultSet.next()) {
final String tableName = resultSet.getString(COLUMN_INDEX);
tableNames.add(tableName);
}
} catch (Exception e) {
e.printStackTrace();
}
}

private void truncate() {
setForeignKeyCheck(OFF);
for (String tableName : tableNames) {
entityManager.createNativeQuery(String.format("TRUNCATE TABLE %s", tableName)).executeUpdate();
}
setForeignKeyCheck(ON);
}

private void setForeignKeyCheck(int mode) {
entityManager.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = %d", mode)).executeUpdate();
}

@Transactional
public void clear() {
if (tableNames.isEmpty()) {
findDatabaseTableNames();
}
entityManager.clear();
truncate();
}
}

0 comments on commit e491214

Please sign in to comment.