겪은 문제
Nested Class로 Test를 진행할 때, Create하는 경우에 비록 해당 테스트 시나리오에서는 매 test마다 DB에 하나씩만 얹어지지만, 시나리오가 유지되므로 PK가 증가하였고, Assertion에서 기대했던 1L이 아닌 2L로 해야만 테스트가 통과되는 문제가 있었다.
재현 방법
@Nested
@DisplayName("POST /v1/members")
class CreateMember {
private final String url = "/v1/members";
@BeforeEach
void setup() {
given(memberImageManager.uploadMemberProfileImage(any())).willReturn(randomString());
}
@Test
@DisplayName("42 OAuth 사용자는 회원 가입을 할 수 있다.")
void createMember() throws Exception {
Member noneRegisteredMember = TestMember.builder()
.oauthId("131541")
.oauthType(OauthType.FORTY_TWO)
.oauthName("sanan")
.memberRole(MemberRole.NOT_REGISTERED)
.build().asMockEntity(1L);
String token = stubToken(noneRegisteredMember, now, 1);
System.out.println("token = " + token);
MockMultipartFile imageFile = new MockMultipartFile("imageData", "test.jpg", "image/jpeg", "test".getBytes());
MockHttpServletRequestBuilder req = multipart(url)
.file(imageFile)
.cookie(new Cookie("access_token", token))
.param("memberName", "sanan")
.param("statement", "안녕하세요?")
.param("categoryFilters", animalCategories.get(0).getCategoryName())
.header(AUTHORIZATION, BEARER + token);
mockMvc.perform(req)
.andDo(print())
.andExpect(status().isOk())
.andDo(result -> {
Member member = em.find(Member.class, noneRegisteredMember.getId());
assertThat(member.getMemberRole()).isEqualTo(MemberRole.USER);
assertThat(member.getOauthProfile().getId()).isEqualTo(noneRegisteredMember.getOauthProfile().getId());
assertThat(member.getOauthProfile().getName()).isEqualTo(noneRegisteredMember.getOauthProfile().getName());
assertThat(member.getOauthProfile().getType()).isEqualTo(noneRegisteredMember.getOauthProfile().getType());
assertThat(member.getNickname()).isEqualTo("sanan");
assertThat(member.getStatement()).isEqualTo("안녕하세요?");
});
}
@DisplayName("프로필 이미지를 업로드하지 않으면 null로 입력된다.")
@Test
void createMember2() throws Exception {
Member noneRegisteredMember = TestMember.builder()
.oauthName("sanan")
.oauthId("sadfasdf")
.oauthType(OauthType.FORTY_TWO)
.nickname("sanan")
.memberRole(MemberRole.NOT_REGISTERED)
.build().asMockEntity(1L);
String token = stubToken(noneRegisteredMember, now, 1);
MockHttpServletRequestBuilder req = multipart(url)
.cookie(new Cookie("access_token", token))
.param("memberName", "sanan")
.param("statement", "안녕하세요?")
.param("categoryFilters", animalCategories.get(0).getCategoryName())
.header(AUTHORIZATION, BEARER + token);
mockMvc.perform(req)
.andDo(print())
.andExpect(status().isOk())
.andDo(e -> {
Member member = em.find(Member.class, noneRegisteredMember.getId());
assertThat(member.getMemberRole()).isEqualTo(MemberRole.USER);
assertThat(member.getOauthProfile().getId()).isEqualTo(noneRegisteredMember.getOauthProfile().getId());
assertThat(member.getOauthProfile().getName()).isEqualTo(noneRegisteredMember.getOauthProfile().getName());
assertThat(member.getOauthProfile().getType()).isEqualTo(noneRegisteredMember.getOauthProfile().getType());
assertThat(member.getNickname()).isEqualTo("sanan");
assertThat(member.getStatement()).isEqualTo("안녕하세요?");
assertThat(member.getProfileImageUrl()).isNull();
});
}
}
Java
복사
시도한 방법
•
2L로 테스트를 성공하게 변경하기
이 방법은 당시에는 테스트가 통과할 수 있으나, 테스트 자체가 순서가 보장되어 있지 않고, 오히려 이를 위해 테스트의 순서를 정하는 것 또한 내키지 않았다.
•
Table의 모든 Data Delete하기
맨 처음에는 @Transactional에도 불구하고 기존의 Data가 남아있어서 2L로 밀리는가 싶어서 BeforeEach로 해당 Table에 있는 데이터들을 DELETE하는 쿼리를 실행했었는데 동일한 문제를 겪었다.
해결법
em.createNativeQuery("ALTER TABLE member ALTER COLUMN id RESTART WITH 1").executeUpdate();
Java
복사
결국 매 테스트마다 해당 Table의 PK 전략, 특히 우리의 경우 auto-increment를 사용 중이었는데, 이 값을 초기화하여 해결했다.