@SpringBootTest // (1)
@AutoConfigureMockMvc // (2)
public class ControllerTestDefaultStructure {
// (3)
@Autowired
private MockMvc mockMvc;
// (4)
@Test
public void postMemberTest() {
// given (5) 테스트용 request body 생성
// when (6) MockMvc 객체로 테스트 대상 Controller 호출
// then (7) Controller 핸들러 메서드에서 응답으로 수신한 HTTP Status 및 response body 검증
}
}
[코드] Controller 테스트용 테스트 클래스 기본 구조
@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private Gson gson;
@Test
void postMemberTest() throws Exception {
// given (1)
MemberDto.Post post = new MemberDto.Post("hgd@gmail.com",
"홍길동",
"010-1234-5678");
String content = gson.toJson(post); // (2)
// when
ResultActions actions =
mockMvc.perform( // (3)
post("/v11/members") // (4)
.accept(MediaType.APPLICATION_JSON) // (5)
.contentType(MediaType.APPLICATION_JSON) // (6)
.content(content) // (7)
);
// then
actions
.andExpect(status().isCreated()) // (8)
.andExpect(header().string("Location", is(startsWith("/v11/members/")))); // (9)
}
}
[코드] MemberController의 postMember() 테스트
@Transactional
@SpringBootTest
@AutoConfigureMockMvc
class MemberControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private Gson gson;
...
...
@Test
void getMemberTest() throws Exception {
// =================================== (1) postMember()를 이용한 테스트 데이터 생성 시작
// given
MemberDto.Post post = new MemberDto.Post("hgd@gmail.com","홍길동","010-1111-1111");
String postContent = gson.toJson(post);
ResultActions postActions =
mockMvc.perform(
post("/v11/members")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(postContent)
);
// =================================== (1) postMember()를 이용한 테스트 데이터 생성 끝
// (2)
String location = postActions.andReturn().getResponse().getHeader("Location"); // "/v11/members/1"
// when / then
mockMvc.perform(
get(location) // (3)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk()) // (4)
.andExpect(jsonPath("$.data.email").value(post.getEmail())) // (5)
.andExpect(jsonPath("$.data.name").value(post.getName())) // (6)
.andExpect(jsonPath("$.data.phone").value(post.getPhone())); // (7)
}
}
[코드] MemberController의 getMember() 테스트
예를들어, test 클래스 내의 전체 테스트 케이스를 실행할 때 다음과 같은 순서로 테스트 케이스가 실행된다고 가정해보자.
실행 순서가 바뀔 경우, WHERE조건의 고정된 상태에서 DB에 조회를 했는데 원하는 결과 값이 없기 때문에 테스트 결과는 "failed"일 것이다.
이처럼 테스트 케이스는 여러 개의 테스트 케이스를 일괄적으로 실행시키더라도 각각의 테스트 케이스에 독립성이 보장되어야 한다.
이러한 문제를 해결하기 위해, DB의 상태를 테스트 케이스 실행 이전으로 되돌려서 깨끗하게 만들어야 한다.
@DataJpaTest // (1)
public class MemberRepositoryTest {
@Autowired
private MemberRepository memberRepository; // (2)
@Test
public void saveMemberTest() {
// given (3)
Member member = new Member();
member.setEmail("hgd@gmail.com");
member.setName("홍길동");
member.setPhone("010-1111-2222");
// when (4)
Member savedMember = memberRepository.save(member);
// then (5)
assertNotNull(savedMember); // (5-1)
assertTrue(member.getEmail().equals(savedMember.getEmail()));
assertTrue(member.getName().equals(savedMember.getName()));
assertTrue(member.getPhone().equals(savedMember.getPhone()));
}
}
[코드[ MemberRepository의 데이터 저장 테스트 예
@DataJpaTest
public class MemberRepositoryTest {
...
...
@Test
public void findByEmailTest() {
// given (1)
Member member = new Member();
member.setEmail("hgd@gmail.com");
member.setName("홍길동");
member.setPhone("010-1111-2222");
// when
memberRepository.save(member); // (2)
Optional<Member> findMember = memberRepository.findByEmail(member.getEmail()); // (3)
// then (4)
assertTrue(findMember.isPresent()); // (4-1)
assertTrue(findMember.get().getEmail().equals(member.getEmail())); // (4-2)
}
}
[코드] MemberRepository의 데이터 조회 테스트