Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] testcontainers로 대체 & 트랜잭션 오류 해결 #55

Merged
merged 6 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ dependencies {

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'com.h2database:h2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.springframework.boot:spring-boot-testcontainers'
testImplementation 'org.testcontainers:testcontainers'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation "org.testcontainers:mariadb:1.19.7"

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
@AutoConfigureTestDatabase(replace = Replace.NONE)
class SignalBuddyApplicationTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void testGetBookmarksWithPagination() {
bookmarkRepository.save(bookmark);
}

/* H2 데이터베이스에서 ST_X 함수 이용 X
/* H2 데이터베이스에서 ST_X 함수 이용 X*/
Pageable pageable = PageRequest.of(0, 5);
Page<BookmarkResponse> bookmarksPage = bookmarkRepository.findPagedByMember(pageable, 1L);

Expand All @@ -62,7 +62,7 @@ void testGetBookmarksWithPagination() {

BookmarkResponse firstBookmark = bookmarksPage.getContent().get(0);
assertThat(firstBookmark.getAddress()).isEqualTo("Address 1");
*/

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import org.programmers.signalbuddy.domain.comment.exception.CommentErrorCode;
import org.programmers.signalbuddy.domain.comment.repository.CommentRepository;
import org.programmers.signalbuddy.domain.feedback.dto.FeedbackWriteRequest;
import org.programmers.signalbuddy.domain.feedback.entity.enums.AnswerStatus;
import org.programmers.signalbuddy.domain.feedback.entity.Feedback;
import org.programmers.signalbuddy.domain.feedback.entity.enums.AnswerStatus;
import org.programmers.signalbuddy.domain.feedback.repository.FeedbackRepository;
import org.programmers.signalbuddy.domain.member.MemberRole;
import org.programmers.signalbuddy.domain.member.entity.Member;
Expand Down Expand Up @@ -119,7 +119,7 @@ void writeCommentByAdmin() {
commentService.writeComment(request, user);

// then
Optional<Comment> actual = commentRepository.findById(4L);
Optional<Comment> actual = commentRepository.findById(2L);
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(actual).get().isNotNull();
softAssertions.assertThat(actual.get().getCommentId()).isNotNull();
Expand Down Expand Up @@ -225,7 +225,7 @@ void deleteCommentByAdmin() {

// when
commentService.writeComment(request, user);
commentService.deleteComment(10L, user);
commentService.deleteComment(2L, user);

// then
SoftAssertions.assertSoftly(softAssertions -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.programmers.signalbuddy.domain.crossroad.dto.CrossroadApiResponse;
import org.programmers.signalbuddy.domain.crossroad.entity.Crossroad;
import org.programmers.signalbuddy.domain.crossroad.repository.CrossroadRepository;
Expand All @@ -18,7 +16,6 @@
import org.springframework.transaction.annotation.Transactional;

@Transactional
@ExtendWith(MockitoExtension.class)
class CrossroadServiceTest extends ServiceTest {

@Autowired
Expand All @@ -30,19 +27,15 @@ class CrossroadServiceTest extends ServiceTest {
@MockitoBean
private CrossroadProvider crossroadProvider;

@DisplayName("Open API를 요청할 때, 페이지 수와 사이즈를 지정하고 다음 해당 데이터 저장")
@DisplayName("Open API를 요청할 때, 페이지 수와 사이즈를 지정하고 가져온 데이터 저장")
@Test
void saveCrossroadDates() {
// given
List<CrossroadApiResponse> expectedList = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
expectedList.add(
CrossroadApiResponse.builder()
.crossroadApiId("aaaaa" + i)
.name("aaaa" + i)
.lat(i * 5.0)
.lng(i * 7.0)
.build());
CrossroadApiResponse.builder().crossroadApiId("aaaaa" + i).name("aaaa" + i)
.lat(i * 5.0).lng(i * 7.0).build());
}

// when
Expand All @@ -53,10 +46,18 @@ void saveCrossroadDates() {
List<Crossroad> actual = crossroadRepository.findAll();
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(actual.size()).isEqualTo(expectedList.size());
softAssertions.assertThat(actual.get(5).getCrossroadApiId()).isEqualTo(expectedList.get(5).getCrossroadApiId());
softAssertions.assertThat(actual.get(5).getName()).isEqualTo(expectedList.get(5).getName());
softAssertions.assertThat(actual.get(5).getCoordinate().getX()).isEqualTo(expectedList.get(5).getLng());
softAssertions.assertThat(actual.get(5).getCoordinate().getY()).isEqualTo(expectedList.get(5).getLat());

softAssertions.assertThat(actual.get(5).getCrossroadApiId())
.isEqualTo(expectedList.get(5).getCrossroadApiId());

softAssertions.assertThat(actual.get(5).getName())
.isEqualTo(expectedList.get(5).getName());

softAssertions.assertThat(actual.get(5).getCoordinate().getX())
.isEqualTo(expectedList.get(5).getLng());

softAssertions.assertThat(actual.get(5).getCoordinate().getY())
.isEqualTo(expectedList.get(5).getLat());
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,28 @@

import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
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.programmers.signalbuddy.domain.feedback.dto.FeedbackResponse;
import org.programmers.signalbuddy.domain.feedback.dto.FeedbackWriteRequest;
import org.programmers.signalbuddy.domain.feedback.entity.Feedback;
import org.programmers.signalbuddy.domain.member.MemberRole;
import org.programmers.signalbuddy.domain.member.entity.Member;
import org.programmers.signalbuddy.domain.member.entity.enums.MemberStatus;
import org.programmers.signalbuddy.domain.member.repository.MemberRepository;
import org.programmers.signalbuddy.global.support.JdbcTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;

@Transactional
@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
class FeedbackJdbcRepositoryTest {
class FeedbackJdbcRepositoryTest extends JdbcTest {

@Autowired
private JdbcTemplate jdbcTemplate;

@Autowired
private FeedbackJdbcRepository feedbackJdbcRepository;
Expand Down Expand Up @@ -50,30 +51,26 @@ void setup() {
feedbackList.add(Feedback.create(request, member));
}
feedbackRepository.saveAll(feedbackList);
}

@AfterEach
void tearDown() {
feedbackRepository.deleteAll();
jdbcTemplate.execute("CREATE FULLTEXT INDEX IF NOT EXISTS idx_subject_content ON feedbacks (subject, content)");
}

// TODO: H2를 MariaDB TestContainers로 바꾸면 테스트 코드 완성하기
@DisplayName("Full Text Search를 이용한 검색 쿼리")
@Test
void fullTextSearch() {
// // when
// Pageable pageable = PageRequest.of(3, 10);
// Page<FeedbackResponse> actual = feedbackJdbcRepository.fullTextSearch(pageable, "test", 0L);
//
// // then
// SoftAssertions.assertSoftly(softAssertions -> {
// softAssertions.assertThat(actual.getTotalElements()).isEqualTo(123);
// softAssertions.assertThat(actual.getTotalPages()).isEqualTo(13);
// softAssertions.assertThat(actual.getNumber()).isEqualTo(3);
// softAssertions.assertThat(actual.getContent().size()).isEqualTo(10);
// softAssertions.assertThat(actual.getContent().get(3).getFeedbackId()).isNotNull();
// softAssertions.assertThat(actual.getContent().get(3).getMember().getMemberId())
// .isEqualTo(member.getMemberId());
// });
// when
Pageable pageable = PageRequest.of(3, 10);
Page<FeedbackResponse> actual = feedbackJdbcRepository.fullTextSearch(pageable, "test", 0L);

// then
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(actual.getTotalElements()).isEqualTo(123);
softAssertions.assertThat(actual.getTotalPages()).isEqualTo(13);
softAssertions.assertThat(actual.getNumber()).isEqualTo(3);
softAssertions.assertThat(actual.getContent().size()).isEqualTo(10);
softAssertions.assertThat(actual.getContent().get(3).getFeedbackId()).isNotNull();
softAssertions.assertThat(actual.getContent().get(3).getMember().getMemberId())
.isEqualTo(member.getMemberId());
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.programmers.signalbuddy.global.config;

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 DataInitializer {

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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.programmers.signalbuddy.global.db;

import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.MariaDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = Replace.NONE)
public interface MariaDBTestContainer {

@Container
MariaDBContainer<?> MARIADB_CONTAINER = new MariaDBContainer<>("mariadb:11.5")
.withDatabaseName("test")
.withUsername("test")
.withPassword("test");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.programmers.signalbuddy.global.support;

import org.junit.jupiter.api.BeforeEach;
import org.programmers.signalbuddy.global.config.DataInitializer;
import org.programmers.signalbuddy.global.db.MariaDBTestContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
@Import(DataInitializer.class)
public abstract class JdbcTest implements MariaDBTestContainer {

@Autowired
private DataInitializer dataInitializer;

@BeforeEach
void delete() {
dataInitializer.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package org.programmers.signalbuddy.global.support;

import org.junit.jupiter.api.BeforeEach;
import org.programmers.signalbuddy.global.config.DataInitializer;
import org.programmers.signalbuddy.global.config.TestQuerydslConfig;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.programmers.signalbuddy.global.db.MariaDBTestContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;

@DataJpaTest
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
@Import(TestQuerydslConfig.class)
public abstract class RepositoryTest {
@Import({TestQuerydslConfig.class, DataInitializer.class})
public abstract class RepositoryTest implements MariaDBTestContainer {

@Autowired
private DataInitializer dataInitializer;

@BeforeEach
void delete() {
dataInitializer.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package org.programmers.signalbuddy.global.support;

import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.programmers.signalbuddy.global.config.DataInitializer;
import org.programmers.signalbuddy.global.db.MariaDBTestContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
public abstract class ServiceTest {
@Import(DataInitializer.class)
@ExtendWith(SpringExtension.class)
public abstract class ServiceTest implements MariaDBTestContainer {

@Autowired
private DataInitializer dataInitializer;

@BeforeEach
void delete() {
dataInitializer.clear();
}
}
Loading
Loading