From 218c136fcf7b74994061df144168e37f487b9dc1 Mon Sep 17 00:00:00 2001 From: thdwoqor Date: Wed, 8 Nov 2023 21:15:39 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20PasswordEncoder=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../digginroom/domain/member/Member.java | 4 +-- .../digginroom/domain/member/Password.java | 10 +++---- .../digginroom/service/MemberService.java | 20 +++++++------ .../service/dto/MemberSaveRequest.java | 5 ---- .../util/DigginRoomPasswordEncoder.java | 10 +++++-- .../digginroom/util/PasswordEncoder.java | 8 ++++++ .../digginroom/digginroom/TestFixture.java | 16 +++++++---- .../digginroom/domain/PasswordTest.java | 17 ++++++----- .../digginroom/service/MemberServiceTest.java | 28 ++++++++++++------- .../digginroom/service/RoomServiceTest.java | 5 ++-- 10 files changed, 75 insertions(+), 48 deletions(-) create mode 100644 backend/src/main/java/com/digginroom/digginroom/util/PasswordEncoder.java diff --git a/backend/src/main/java/com/digginroom/digginroom/domain/member/Member.java b/backend/src/main/java/com/digginroom/digginroom/domain/member/Member.java index f36aef8b5..292c14b45 100644 --- a/backend/src/main/java/com/digginroom/digginroom/domain/member/Member.java +++ b/backend/src/main/java/com/digginroom/digginroom/domain/member/Member.java @@ -47,8 +47,8 @@ private Member(final String username, final Password password, final Provider pr this.nickname = nickname; } - public static Member self(final String username, final String password) { - return new Member(username, new Password(password), Provider.SELF, Nickname.random()); + public static Member self(final String username, final Password password) { + return new Member(username, password, Provider.SELF, Nickname.random()); } public static Member social(final String username, final Provider provider, final String nickname) { diff --git a/backend/src/main/java/com/digginroom/digginroom/domain/member/Password.java b/backend/src/main/java/com/digginroom/digginroom/domain/member/Password.java index adb435c83..24076e4fa 100644 --- a/backend/src/main/java/com/digginroom/digginroom/domain/member/Password.java +++ b/backend/src/main/java/com/digginroom/digginroom/domain/member/Password.java @@ -1,6 +1,6 @@ package com.digginroom.digginroom.domain.member; -import com.digginroom.digginroom.util.DigginRoomPasswordEncoder; +import com.digginroom.digginroom.util.PasswordEncoder; import jakarta.persistence.Embeddable; import lombok.AccessLevel; import lombok.Getter; @@ -17,15 +17,15 @@ public class Password { private String password = EMPTY_PASSWORD; - public Password(final String password) { - this.password = DigginRoomPasswordEncoder.encode(password); + public Password(final String password, final PasswordEncoder passwordEncoder) { + this.password = passwordEncoder.encode(password); } - public boolean doesNotMatch(final String password) { + public boolean doesNotMatch(final String password, final PasswordEncoder passwordEncoder) { if (this.isEmpty()) { return false; } - return !DigginRoomPasswordEncoder.matches(password, this.password); + return !passwordEncoder.matches(password, this.password); } public boolean isEmpty() { diff --git a/backend/src/main/java/com/digginroom/digginroom/service/MemberService.java b/backend/src/main/java/com/digginroom/digginroom/service/MemberService.java index 902fc4dcf..94f6641af 100644 --- a/backend/src/main/java/com/digginroom/digginroom/service/MemberService.java +++ b/backend/src/main/java/com/digginroom/digginroom/service/MemberService.java @@ -1,13 +1,8 @@ package com.digginroom.digginroom.service; -import com.digginroom.digginroom.service.dto.FavoriteGenresRequest; -import com.digginroom.digginroom.service.dto.MemberDetailsResponse; -import com.digginroom.digginroom.service.dto.MemberDuplicationResponse; -import com.digginroom.digginroom.service.dto.MemberLoginRequest; -import com.digginroom.digginroom.service.dto.MemberLoginResponse; -import com.digginroom.digginroom.service.dto.MemberSaveRequest; import com.digginroom.digginroom.domain.Genre; import com.digginroom.digginroom.domain.member.Member; +import com.digginroom.digginroom.domain.member.Password; import com.digginroom.digginroom.domain.member.Provider; import com.digginroom.digginroom.exception.MemberException.DuplicationException; import com.digginroom.digginroom.exception.MemberException.NotFoundException; @@ -15,6 +10,13 @@ import com.digginroom.digginroom.oauth.IdTokenResolver; import com.digginroom.digginroom.oauth.payload.IdTokenPayload; import com.digginroom.digginroom.repository.MemberRepository; +import com.digginroom.digginroom.service.dto.FavoriteGenresRequest; +import com.digginroom.digginroom.service.dto.MemberDetailsResponse; +import com.digginroom.digginroom.service.dto.MemberDuplicationResponse; +import com.digginroom.digginroom.service.dto.MemberLoginRequest; +import com.digginroom.digginroom.service.dto.MemberLoginResponse; +import com.digginroom.digginroom.service.dto.MemberSaveRequest; +import com.digginroom.digginroom.util.PasswordEncoder; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -27,13 +29,15 @@ public class MemberService { private final MemberRepository memberRepository; private final IdTokenResolver idTokenResolver; + private final PasswordEncoder passwordEncoder; public void save(final MemberSaveRequest request) { if (isDuplicated(request.username())) { throw new DuplicationException(); } - memberRepository.save(request.toMember()); + Password password = new Password(request.password(), passwordEncoder); + memberRepository.save(Member.self(request.username(), password)); } private boolean isDuplicated(final String username) { @@ -73,7 +77,7 @@ public MemberLoginResponse loginMember(final MemberLoginRequest request) { throw new WrongProviderException(); } - if (member.getPassword().doesNotMatch(request.password())) { + if (member.getPassword().doesNotMatch(request.password(), passwordEncoder)) { throw new NotFoundException(); } return MemberLoginResponse.of(member); diff --git a/backend/src/main/java/com/digginroom/digginroom/service/dto/MemberSaveRequest.java b/backend/src/main/java/com/digginroom/digginroom/service/dto/MemberSaveRequest.java index 4fc5144ed..5b8954889 100644 --- a/backend/src/main/java/com/digginroom/digginroom/service/dto/MemberSaveRequest.java +++ b/backend/src/main/java/com/digginroom/digginroom/service/dto/MemberSaveRequest.java @@ -1,6 +1,5 @@ package com.digginroom.digginroom.service.dto; -import com.digginroom.digginroom.domain.member.Member; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; @@ -21,8 +20,4 @@ public record MemberSaveRequest( ) String password ) { - - public Member toMember() { - return Member.self(username, password); - } } diff --git a/backend/src/main/java/com/digginroom/digginroom/util/DigginRoomPasswordEncoder.java b/backend/src/main/java/com/digginroom/digginroom/util/DigginRoomPasswordEncoder.java index 8e3a6784d..31e80c3ab 100644 --- a/backend/src/main/java/com/digginroom/digginroom/util/DigginRoomPasswordEncoder.java +++ b/backend/src/main/java/com/digginroom/digginroom/util/DigginRoomPasswordEncoder.java @@ -1,19 +1,23 @@ package com.digginroom.digginroom.util; import java.util.UUID; +import org.springframework.stereotype.Component; -public class DigginRoomPasswordEncoder { +@Component +public class DigginRoomPasswordEncoder implements PasswordEncoder { private static final int SALT_LENGTH = 36; private static final int SALT_START_INDEX = 0; - public static String encode(final String plainText) { + @Override + public String encode(final String plainText) { UUID salt = UUID.randomUUID(); String hashed = HashAlgorithm.encrypt(salt + plainText); return salt + hashed; } - public static boolean matches(final String plainText, final String encoded) { + @Override + public boolean matches(final String plainText, final String encoded) { String salt = encoded.substring(SALT_START_INDEX, SALT_LENGTH); String hashed = HashAlgorithm.encrypt(salt + plainText); return (salt + hashed).equals(encoded); diff --git a/backend/src/main/java/com/digginroom/digginroom/util/PasswordEncoder.java b/backend/src/main/java/com/digginroom/digginroom/util/PasswordEncoder.java new file mode 100644 index 000000000..61124cc7d --- /dev/null +++ b/backend/src/main/java/com/digginroom/digginroom/util/PasswordEncoder.java @@ -0,0 +1,8 @@ +package com.digginroom.digginroom.util; + +public interface PasswordEncoder { + + String encode(final String plainText); + + boolean matches(final String plainText, final String encoded); +} diff --git a/backend/src/test/java/com/digginroom/digginroom/TestFixture.java b/backend/src/test/java/com/digginroom/digginroom/TestFixture.java index d1a993149..c35eb294c 100644 --- a/backend/src/test/java/com/digginroom/digginroom/TestFixture.java +++ b/backend/src/test/java/com/digginroom/digginroom/TestFixture.java @@ -1,10 +1,8 @@ package com.digginroom.digginroom; -import com.digginroom.digginroom.service.dto.CommentRequest; -import com.digginroom.digginroom.service.dto.MemberLoginRequest; -import com.digginroom.digginroom.service.dto.MemberSaveRequest; import com.digginroom.digginroom.domain.Genre; import com.digginroom.digginroom.domain.member.Member; +import com.digginroom.digginroom.domain.member.Password; import com.digginroom.digginroom.domain.member.Provider; import com.digginroom.digginroom.domain.room.Room; import com.digginroom.digginroom.domain.track.Track; @@ -13,7 +11,10 @@ import com.digginroom.digginroom.oauth.jwk.KakaoJwkProvider; import com.digginroom.digginroom.oauth.jwk.ThirdPartyJwkProviders; import com.digginroom.digginroom.oauth.payload.IdTokenPayload; - +import com.digginroom.digginroom.service.dto.CommentRequest; +import com.digginroom.digginroom.service.dto.MemberLoginRequest; +import com.digginroom.digginroom.service.dto.MemberSaveRequest; +import com.digginroom.digginroom.util.DigginRoomPasswordEncoder; import java.util.List; //TODO: 픽스쳐 분리 @@ -30,12 +31,15 @@ public class TestFixture { public static final MemberLoginRequest MEMBER2_LOGIN_REQUEST = new MemberLoginRequest(MEMBER2_USERNAME, MEMBER2_PASSWORD); + public static Password PASSWORD = new Password(MEMBER_PASSWORD, new DigginRoomPasswordEncoder()); + public static Password PASSWORD2 = new Password(MEMBER2_PASSWORD, new DigginRoomPasswordEncoder()); + public static Member 파워() { - return Member.self(MEMBER_USERNAME, MEMBER_PASSWORD); + return Member.self(MEMBER_USERNAME, PASSWORD); } public static Member 블랙캣() { - return Member.self(MEMBER2_USERNAME, MEMBER2_PASSWORD); + return Member.self(MEMBER2_USERNAME, PASSWORD2); } public static final CommentRequest COMMENT_REQUEST = new CommentRequest("베리는 REST API 고수"); diff --git a/backend/src/test/java/com/digginroom/digginroom/domain/PasswordTest.java b/backend/src/test/java/com/digginroom/digginroom/domain/PasswordTest.java index 050b1446d..65454fe01 100644 --- a/backend/src/test/java/com/digginroom/digginroom/domain/PasswordTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/domain/PasswordTest.java @@ -3,6 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import com.digginroom.digginroom.domain.member.Password; +import com.digginroom.digginroom.util.DigginRoomPasswordEncoder; +import com.digginroom.digginroom.util.PasswordEncoder; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; @@ -11,37 +13,38 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class PasswordTest { + private static final PasswordEncoder passwordEncoder = new DigginRoomPasswordEncoder(); private static final String PLAIN_TEXT = "konghanapassword"; @Test void 패스워드를_직접_생성하면_암호화된_패스워드가_생성된다() { - Password password = new Password(PLAIN_TEXT); + Password password = new Password(PLAIN_TEXT, passwordEncoder); assertThat(password.getPassword()).isNotEqualTo(PLAIN_TEXT); } @Test void 빈_패스워드인지_확인할_수_있다() { - assertThat(new Password(PLAIN_TEXT).isEmpty()).isFalse(); + assertThat(new Password(PLAIN_TEXT, passwordEncoder).isEmpty()).isFalse(); assertThat(Password.EMPTY.isEmpty()).isTrue(); } @Test void 패스워드가_일치하는지_확인할_수_있다() { - Password password = new Password(PLAIN_TEXT); + Password password = new Password(PLAIN_TEXT, passwordEncoder); - assertThat(password.doesNotMatch(PLAIN_TEXT)).isFalse(); + assertThat(password.doesNotMatch(PLAIN_TEXT, passwordEncoder)).isFalse(); } @Test void 패스워드가_일치하지_않는지_확인할_수_있다() { - Password password = new Password(PLAIN_TEXT); + Password password = new Password(PLAIN_TEXT, passwordEncoder); - assertThat(password.doesNotMatch("anotherpassword")).isTrue(); + assertThat(password.doesNotMatch("anotherpassword", passwordEncoder)).isTrue(); } @Test void 빈_패스워드는_어떤_문자열과도_일치하지_않는다() { - assertThat(Password.EMPTY.doesNotMatch("")).isFalse(); + assertThat(Password.EMPTY.doesNotMatch("", passwordEncoder)).isFalse(); } } diff --git a/backend/src/test/java/com/digginroom/digginroom/service/MemberServiceTest.java b/backend/src/test/java/com/digginroom/digginroom/service/MemberServiceTest.java index d49262d0f..48df5869c 100644 --- a/backend/src/test/java/com/digginroom/digginroom/service/MemberServiceTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/service/MemberServiceTest.java @@ -1,6 +1,8 @@ package com.digginroom.digginroom.service; import static com.digginroom.digginroom.TestFixture.ID_TOKEN_PAYLOAD; +import static com.digginroom.digginroom.TestFixture.MEMBER_PASSWORD; +import static com.digginroom.digginroom.TestFixture.PASSWORD; import static com.digginroom.digginroom.TestFixture.파워; import static com.digginroom.digginroom.domain.Genre.DANCE; import static com.digginroom.digginroom.domain.Genre.ROCK; @@ -11,14 +13,15 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.digginroom.digginroom.service.dto.FavoriteGenresRequest; -import com.digginroom.digginroom.service.dto.MemberLoginRequest; -import com.digginroom.digginroom.service.dto.MemberLoginResponse; -import com.digginroom.digginroom.service.dto.MemberSaveRequest; import com.digginroom.digginroom.domain.member.Member; import com.digginroom.digginroom.exception.MemberException; import com.digginroom.digginroom.oauth.IdTokenResolver; import com.digginroom.digginroom.repository.MemberRepository; +import com.digginroom.digginroom.service.dto.FavoriteGenresRequest; +import com.digginroom.digginroom.service.dto.MemberLoginRequest; +import com.digginroom.digginroom.service.dto.MemberLoginResponse; +import com.digginroom.digginroom.service.dto.MemberSaveRequest; +import com.digginroom.digginroom.util.PasswordEncoder; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.DisplayNameGeneration; @@ -38,6 +41,8 @@ class MemberServiceTest { private MemberRepository memberRepository; @Mock private IdTokenResolver idTokenResolver; + @Mock + private PasswordEncoder passwordEncoder; @InjectMocks private MemberService memberService; @@ -46,7 +51,9 @@ class MemberServiceTest { when(memberRepository.existsByUsername("power")) .thenReturn(false); - memberService.save(new MemberSaveRequest("power", "power")); + when(passwordEncoder.encode(MEMBER_PASSWORD)).thenReturn(PASSWORD.getPassword()); + + memberService.save(new MemberSaveRequest("power", MEMBER_PASSWORD)); verify(memberRepository).save(any(Member.class)); } @@ -71,10 +78,10 @@ class MemberServiceTest { @Test void 회원_정보가_있다면_로그인_할_수_있다() { - Member power = Member.self("power", "power123!"); + Member power = Member.self("power", PASSWORD); when(memberRepository.getMemberByUsername("power")).thenReturn(power); - - assertThat(memberService.loginMember(new MemberLoginRequest(power.getUsername(), "power123!"))) + when(passwordEncoder.matches(MEMBER_PASSWORD, PASSWORD.getPassword())).thenReturn(true); + assertThat(memberService.loginMember(new MemberLoginRequest(power.getUsername(), MEMBER_PASSWORD))) .isEqualTo(MemberLoginResponse.of(power)); } @@ -88,11 +95,12 @@ class MemberServiceTest { @Test void 비밀번호가_틀리면_로그인_할_수_없다() { - Member power = Member.self("power", "power123!"); + Member power = Member.self("power", PASSWORD); when(memberRepository.getMemberByUsername("power")).thenReturn(power); + when(passwordEncoder.matches(MEMBER_PASSWORD + "asd", PASSWORD.getPassword())).thenReturn(false); assertThatThrownBy(() -> memberService.loginMember( - new MemberLoginRequest(power.getUsername(), power.getPassword() + "asd"))) + new MemberLoginRequest(power.getUsername(), MEMBER_PASSWORD + "asd"))) .isInstanceOf(MemberException.NotFoundException.class); } diff --git a/backend/src/test/java/com/digginroom/digginroom/service/RoomServiceTest.java b/backend/src/test/java/com/digginroom/digginroom/service/RoomServiceTest.java index 30afef6f2..ae168c37b 100644 --- a/backend/src/test/java/com/digginroom/digginroom/service/RoomServiceTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/service/RoomServiceTest.java @@ -1,5 +1,6 @@ package com.digginroom.digginroom.service; +import static com.digginroom.digginroom.TestFixture.PASSWORD; import static com.digginroom.digginroom.TestFixture.나무; import static com.digginroom.digginroom.TestFixture.차이; import static com.digginroom.digginroom.TestFixture.파워; @@ -54,7 +55,7 @@ class RoomServiceTest { @Test void 스크랩_항목이_있는_경우_멤버가_스크랩한_룸_목록을_조회할_수_있다() { - Member member = memberRepository.save(Member.self("member", "1234")); + Member member = memberRepository.save(Member.self("member", PASSWORD)); Room 나무 = 나무(); Room 차이 = 차이(); roomRepository.save(나무); @@ -83,7 +84,7 @@ class RoomServiceTest { @Test void 스크랩_항목이_없는_경우_멤버가_빈_룸_목록을_조회할_수_있다() { - Member member = memberRepository.save(Member.self("member", "1234")); + Member member = memberRepository.save(Member.self("member", PASSWORD)); RoomsResponse scrappedRooms = roomService.findScrappedRooms(member.getId()); From 69668841bf51f2a5815de214e54e30c56ad13c98 Mon Sep 17 00:00:00 2001 From: thdwoqor Date: Wed, 8 Nov 2023 21:18:35 +0900 Subject: [PATCH 2/5] =?UTF-8?q?test:=20DirtiesContext=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CommentControllerTest.java | 3 +- .../digginroom/controller/ControllerTest.java | 29 +++++++++++++++++++ .../MemberArgumentResolverTest.java | 2 -- .../controller/MemberLoginControllerTest.java | 2 -- .../MemberOperationControllerTest.java | 2 -- .../controller/RoomControllerTest.java | 2 -- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/CommentControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/CommentControllerTest.java index 6eb90d0ee..3f028090d 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/CommentControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/CommentControllerTest.java @@ -28,10 +28,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class CommentControllerTest extends ControllerTest { @Autowired @@ -40,6 +38,7 @@ class CommentControllerTest extends ControllerTest { private RoomRepository roomRepository; @Autowired private CommentRepository commentRepository; + private Room 나무; private Room 차이; private Member 파워; diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java index 420dfdf02..9d8395fa9 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java @@ -2,17 +2,23 @@ import io.restassured.RestAssured; +import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.jdbc.core.JdbcTemplate; @DisplayNameGeneration(ReplaceUnderscores.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public abstract class ControllerTest { + @Autowired + private JdbcTemplate jdbcTemplate; @LocalServerPort private int port; @@ -20,4 +26,27 @@ public abstract class ControllerTest { void setUp() { RestAssured.port = port; } + + @AfterEach + public void afterEach() { + final List truncateQueries = getTruncateQueries(jdbcTemplate); + truncateTables(jdbcTemplate, truncateQueries); + } + + private List getTruncateQueries(final JdbcTemplate jdbcTemplate) { + return jdbcTemplate.queryForList( + "SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY;') AS q " + + "FROM INFORMATION_SCHEMA.TABLES " + + "WHERE TABLE_SCHEMA = 'PUBLIC'", String.class); + } + + private void truncateTables(final JdbcTemplate jdbcTemplate, final List truncateQueries) { + execute(jdbcTemplate, "SET REFERENTIAL_INTEGRITY FALSE"); + truncateQueries.forEach(v -> execute(jdbcTemplate, v)); + execute(jdbcTemplate, "SET REFERENTIAL_INTEGRITY TRUE"); + } + + private void execute(final JdbcTemplate jdbcTemplate, final String query) { + jdbcTemplate.execute(query); + } } diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/MemberArgumentResolverTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/MemberArgumentResolverTest.java index 1f5e934b7..3c896c82f 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/MemberArgumentResolverTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/MemberArgumentResolverTest.java @@ -8,10 +8,8 @@ import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class MemberArgumentResolverTest extends ControllerTest { @Test diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/MemberLoginControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/MemberLoginControllerTest.java index 95e1a06a8..a335a7ac6 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/MemberLoginControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/MemberLoginControllerTest.java @@ -9,14 +9,12 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; import static com.digginroom.digginroom.TestFixture.MEMBER_LOGIN_REQUEST; import static com.digginroom.digginroom.TestFixture.파워; import static org.hamcrest.Matchers.*; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class MemberLoginControllerTest extends ControllerTest { @Autowired diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/MemberOperationControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/MemberOperationControllerTest.java index 51806322d..0b35956c8 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/MemberOperationControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/MemberOperationControllerTest.java @@ -16,10 +16,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class MemberOperationControllerTest extends ControllerTest { private String cookie; diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/RoomControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/RoomControllerTest.java index b220f392e..94915424a 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/RoomControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/RoomControllerTest.java @@ -25,10 +25,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class RoomControllerTest extends ControllerTest { @Autowired From acefe7f29bba188359b039f214389233df4af0dd Mon Sep 17 00:00:00 2001 From: songusika Date: Tue, 14 Nov 2023 21:34:54 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9A=A9=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../digginroom/controller/ControllerTest.java | 32 ++----------- .../digginroom/util/DatabaseCleaner.java | 45 +++++++++++++++++++ .../util/DatabaseCleanerExtension.java | 15 +++++++ 3 files changed, 63 insertions(+), 29 deletions(-) create mode 100644 backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleaner.java create mode 100644 backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleanerExtension.java diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java index 9d8395fa9..5907bf070 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/ControllerTest.java @@ -1,24 +1,21 @@ package com.digginroom.digginroom.controller; +import com.digginroom.digginroom.util.DatabaseCleanerExtension; import io.restassured.RestAssured; -import java.util.List; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.jdbc.core.JdbcTemplate; +@ExtendWith(DatabaseCleanerExtension.class) @DisplayNameGeneration(ReplaceUnderscores.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public abstract class ControllerTest { - @Autowired - private JdbcTemplate jdbcTemplate; @LocalServerPort private int port; @@ -26,27 +23,4 @@ public abstract class ControllerTest { void setUp() { RestAssured.port = port; } - - @AfterEach - public void afterEach() { - final List truncateQueries = getTruncateQueries(jdbcTemplate); - truncateTables(jdbcTemplate, truncateQueries); - } - - private List getTruncateQueries(final JdbcTemplate jdbcTemplate) { - return jdbcTemplate.queryForList( - "SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ' RESTART IDENTITY;') AS q " - + "FROM INFORMATION_SCHEMA.TABLES " - + "WHERE TABLE_SCHEMA = 'PUBLIC'", String.class); - } - - private void truncateTables(final JdbcTemplate jdbcTemplate, final List truncateQueries) { - execute(jdbcTemplate, "SET REFERENTIAL_INTEGRITY FALSE"); - truncateQueries.forEach(v -> execute(jdbcTemplate, v)); - execute(jdbcTemplate, "SET REFERENTIAL_INTEGRITY TRUE"); - } - - private void execute(final JdbcTemplate jdbcTemplate, final String query) { - jdbcTemplate.execute(query); - } } diff --git a/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleaner.java b/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleaner.java new file mode 100644 index 000000000..6f8dd37e4 --- /dev/null +++ b/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleaner.java @@ -0,0 +1,45 @@ +package com.digginroom.digginroom.util; + +import jakarta.annotation.PostConstruct; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class DatabaseCleaner { + + @Autowired + private EntityManager entityManager; + private List tableNames; + + @PostConstruct + private void setUpDatabaseTableNames() { + this.tableNames = getTableNames(); + } + + private List getTableNames() { + return getTableMetaData().stream().map(this::getTableName).toList(); + } + + @SuppressWarnings("unchecked") + private List getTableMetaData() { + return entityManager.createNativeQuery("SHOW TABLES").getResultList(); + } + + private String getTableName(final Object[] tableInfos) { + return (String) tableInfos[0]; + } + + @Transactional + public void clear() { + executeQuery("SET REFERENTIAL_INTEGRITY FALSE;"); + tableNames.forEach(tableName -> executeQuery("TRUNCATE TABLE " + tableName + " RESTART IDENTITY;")); + executeQuery("SET REFERENTIAL_INTEGRITY TRUE;"); + } + + private void executeQuery(final String query) { + entityManager.createNativeQuery(query).executeUpdate(); + } +} diff --git a/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleanerExtension.java b/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleanerExtension.java new file mode 100644 index 000000000..d9924c94f --- /dev/null +++ b/backend/src/test/java/com/digginroom/digginroom/util/DatabaseCleanerExtension.java @@ -0,0 +1,15 @@ +package com.digginroom.digginroom.util; + +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +public class DatabaseCleanerExtension implements BeforeEachCallback { + + @Override + public void beforeEach(final ExtensionContext context) { + SpringExtension.getApplicationContext(context) + .getBean(DatabaseCleaner.class) + .clear(); + } +} From e60467e3a5d4e9c2ce56125d3102b864a771c483 Mon Sep 17 00:00:00 2001 From: songusika Date: Thu, 16 Nov 2023 17:03:16 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=EB=82=A8=EC=95=84=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20DirtContext=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberJoinControllerTest.java | 2 -- .../feedback/controller/FeedbackControllerTest.java | 10 ++++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/backend/src/test/java/com/digginroom/digginroom/controller/MemberJoinControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/controller/MemberJoinControllerTest.java index a521c3325..0b6a756ab 100644 --- a/backend/src/test/java/com/digginroom/digginroom/controller/MemberJoinControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/controller/MemberJoinControllerTest.java @@ -7,10 +7,8 @@ import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; @SuppressWarnings("NonAsciiCharacters") -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class MemberJoinControllerTest extends ControllerTest { @Test diff --git a/backend/src/test/java/com/digginroom/digginroom/feedback/controller/FeedbackControllerTest.java b/backend/src/test/java/com/digginroom/digginroom/feedback/controller/FeedbackControllerTest.java index 01900cbeb..a9e0dc94f 100644 --- a/backend/src/test/java/com/digginroom/digginroom/feedback/controller/FeedbackControllerTest.java +++ b/backend/src/test/java/com/digginroom/digginroom/feedback/controller/FeedbackControllerTest.java @@ -1,5 +1,9 @@ package com.digginroom.digginroom.feedback.controller; +import static com.digginroom.digginroom.TestFixture.MEMBER_LOGIN_REQUEST; +import static com.digginroom.digginroom.TestFixture.파워; +import static org.assertj.core.api.Assertions.assertThat; + import com.digginroom.digginroom.TestFixture; import com.digginroom.digginroom.controller.ControllerTest; import com.digginroom.digginroom.feedback.domain.Feedback; @@ -17,15 +21,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.test.annotation.DirtiesContext; - -import static com.digginroom.digginroom.TestFixture.MEMBER_LOGIN_REQUEST; -import static com.digginroom.digginroom.TestFixture.파워; -import static org.assertj.core.api.Assertions.assertThat; @SuppressWarnings("NonAsciiCharacters") @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class FeedbackControllerTest extends ControllerTest { @Autowired From ff12e8c121f007ef787a8860ee32cfc57f20ad8e Mon Sep 17 00:00:00 2001 From: songusika Date: Thu, 16 Nov 2023 17:09:59 +0900 Subject: [PATCH 5/5] =?UTF-8?q?remove:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../digginroom/digginroom/util/TestClaim.java | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 backend/src/test/java/com/digginroom/digginroom/util/TestClaim.java diff --git a/backend/src/test/java/com/digginroom/digginroom/util/TestClaim.java b/backend/src/test/java/com/digginroom/digginroom/util/TestClaim.java deleted file mode 100644 index db5f93ac8..000000000 --- a/backend/src/test/java/com/digginroom/digginroom/util/TestClaim.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.digginroom.digginroom.util; - -import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.interfaces.Claim; -import java.util.Date; -import java.util.List; -import java.util.Map; - -public class TestClaim implements Claim { - - private final String value; - - public TestClaim(final String value) { - this.value = value; - } - - @Override - public boolean isNull() { - return false; - } - - @Override - public Boolean asBoolean() { - return null; - } - - @Override - public Integer asInt() { - return null; - } - - @Override - public Long asLong() { - return null; - } - - @Override - public Double asDouble() { - return null; - } - - @Override - public String asString() { - return value; - } - - @Override - public Date asDate() { - return null; - } - - @Override - public T[] asArray(final Class tClazz) throws JWTDecodeException { - return null; - } - - @Override - public List asList(final Class tClazz) throws JWTDecodeException { - return null; - } - - @Override - public Map asMap() throws JWTDecodeException { - return null; - } - - @Override - public T as(final Class tClazz) throws JWTDecodeException { - return null; - } -}