이번 글에서는 JUnit5와 mokito를 활용한 MVC테스트 하는 방법에 대해 정리 해보려고 한다.
🍥JUnit5
JUnit5 정리 :
https://record1996.tistory.com/75
JUnit이란?
🐾 JUnit Junit은 Java를 위한 Unit 테스트 프레임워크이다. 서버를 구동하지 않고도 테스트가 가능하기 때문에 많은 개발자들에 의해 많이 사용된다. 또 Java 8 이상부터 사용 가능하다! ⭐Unit(단위)
record1996.tistory.com
블로그에 글을 써두긴 했지만 간단하게 정리하자면
JUnit5는 Java를 위한 단위 테스트 프레임 워크로
서버를 구동하지 않고도 테스트가 가능한 간편성 때문에 자바 개발자들이 대부분 사용한다고 한다!
🍸mokito
모키토는 자바에서 단위테스트를 진행하면서 모의(mock) 객체를 생성하고 사용할 수 있도록 도와주는 라이브러리이다.
예를 들어 나의 경우 처음 테스트를 진행할 때 MVC패턴 중 컨트롤러 테스트를 진행 하려고 했는데 repository,service,entity가 모두 연결이 되어있다보니 어떻게 컨트롤러만 단위 테스트를 진행해야 하는건지를 고민하게 되었다.
이 경우에 mokito를 이용하면 repository,service,entity를 가짜 객체로 만들어 컨트롤러만 독립적으로 테스트 할 수 있게 되는 것이다.
이와 같이 모의 객체를 사용하면 코드를 독립적으로 테스트가 가능하고, 시스템과의 상호작용을 최소하하여 더 빠르게 테스트를 진행 할 수 있다!
🥟SpringBoot 사용 설정
testImplementation 'org.springframework.boot:spring-boot-starter-test'
스프링부트 2.2부터는 spring-boot-starter-test 의존성이 기본으로 포함되어 있는데
위 라이브러리에는 JUnit5,Mokito 등의 다양한 테스트 관련 기능을 포함하고 있다.
🍠TEST
1. 기능 설명
간단한 MVC패턴의 회원가입 기능과 전체 회원 정보 조회 기능을 만들어 보았다!
차례로
1. index.html
2. signResult.html - 회원가입이 되면 보이는 페이지 <전체 회원 정보 보기>클릭시 3으로 이동
3. allView.html - 가입한 회원의 정보를 볼수 있는 페이지
2. MVC 설계
Member 클래스
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Member {
@Id
private String id;
private String pw;
private String name;
}
MemberDao 인터페이스
@Repository
public interface MemberDao extends JpaRepository<Member, String>{
}
MemberService 인터페이스
@Service
public interface MemberService {
public void Join(String id, String pw,String name);
public List<Member> MemberList();
}
MemberServiceImpl 클래스
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
MemberDao memberDao;
//가입
@Override
public void Join(String id, String pw,String name) {
memberDao.save(new Member(id,pw,name));
}
//전체 회원 조회
@Override
public List<Member> MemberList(){
return memberDao.findAll();
}
}
MemberController 클래스
@Controller
@RequestMapping("member")
public class MemberController {
@Autowired
MemberService memberService;
//가입
@PostMapping("join")
public String join(@RequestParam("id") String id,
@RequestParam("pw") String pw,
@RequestParam("name") String name) {
memberService.Join(id, pw, name);
return "member/signResult";
}
//전체 회원 조회
@GetMapping("memberList")
public String MemberList(Model model){
model.addAttribute("memberList", memberService.MemberList());
return "member/allView";
}
}
3. 테스트 코드 작성
전체 회원 정보 조회 테스트
@WebMvcTest(MemberController.class)// 컨트롤러를 테스트 할 때 주로 사용
public class MemberControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
MemberService memberService;
@Test
@DisplayName("All Member List Test")
public void AllMemberList() {
List<Member> member = new ArrayList<>();
member.add(new Member("abc","123","백종원"));
when(memberService.MemberList()).thenReturn(member);
try {
mockMvc.perform(get("/member/memberList"))
.andExpect(status().isOk())
.andExpect(view().name("member/allView"))
.andExpect(model().attributeExists("memberList"))
.andExpect(model().attribute("memberList", member));
} catch (Exception e) {
e.printStackTrace();
}
}
}
- @MockBean - 스프링 프레임워크로 테스트할 때 주로 사용되며 모의 빈을 생성하여 주입함
- when - Mock 객체의 행동을 설정할 수 있음 👉 위 코드의 경우 memberService의 행동을 설정하는 것으로 memberService의 MemberList()가 호출될 때 member 리스트를 반환하도록 설정하였다.
- mockMvc.perform(get("/member/memberList")) - /member/memberList에 get 요청을 보냄
- andExpect - 응답을 검증하는 역할 / 실행시 기대되는 행동을 검증함
- andExpect(status().isOk()) - memberList 컨트롤러 실행 상태가 정상(200)인지 검증
- .andExpect(view().name("member/allView")) - memberList 컨트롤러는 동작이 끝나면 member/allView를 반환되도록 되어 있어 그 부분을 검증
- .andExpect(model().attributeExists("memberList")) - memberList 컨트롤러는 모델에 memberList를 담아 뷰에 전달하도록 설계되어 있어 그 부분을 검증(model에 memberList가 존재하는지 확인)
- .andExpect(model().attribute("memberList", member)) - model에 memberList가 가짜 데이터인 member와 일치하는지 확인
회원 가입 테스트
@WebMvcTest(MemberController.class)
public class MemberControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
MemberService memberService;
@Test
@DisplayName("Join Member Test")
public void Join() {
String id = "abc";
String pw = "123";
String name = "백종원";//테스트에 사용할 데이터
doNothing().when(memberService).Join(id, pw, name);
try {
mockMvc.perform(post("/member/join")
.param("id", id)
.param("pw", pw)
.param("name", name))
.andExpect(status().isOk())
.andExpect(view().name("member/signResult"));
}catch(Exception e) {
e.printStackTrace();
}
verify(memberService).Join(id, pw, name);
}
}
- doNothing() - 메서드 호출 시 아무런 동작을 수행하지 않도록 설정
- doNothing().when(memberService).Join(id, pw, name) - memberService가 Join() 호출 시 아무 동작도 수행하지 않도록 설정 (memberService의 Join() 메소드가 반환타입이 void여서 doNothing()으로 설정해둠)
- mockMvc.perform(post("/member/join") - /member/join에 post 요청
- .param() - 키,값의 파라미터를 전달 / 컨트롤러의 Join()이 @RequestParam으로 id,pw,name을 받도록 되어 있기 때문에 이를 전달해줌
- .andExpect(status().isOk()) - 실행 시 정상 상태인지 검증
- .andExpect(view().name("member/signResult")); - 실행 시 member/signResult 뷰를 반환하는지 검증
- verify(mock).method(param) - 해당 Mock이 메소드를 호출했는지 검증
- verify(memberService).Join(id, pw, name) - memberService의 Join()이 id,pw,name를 매개변수로 호출된건지 검증 (즉, 컨트롤러에서 memberService의 Join()을 호출했는지 검증한다.)
정리를 하면서 아직 너무나도 부족하다고 느꼈다 ㅎㅎ
지속적으로 테스트 코드를 작성하며 점차 실력을 늘려야지 ...
'🌱 Spring' 카테고리의 다른 글
Page<Entity> 👉 Page<DTO> 매핑하기(+mapstruct로 page 매핑시 에러) (0) | 2024.02.23 |
---|---|
[springboot]mapstruct로 entity와 dto 매핑하기 (0) | 2024.02.22 |
JUnit이란? (0) | 2023.10.12 |
스프링 빈(Spring Bean)이란? (0) | 2023.09.26 |
Spring과 SpringBoot의 차이점 (0) | 2023.09.20 |