본문 바로가기

Java/Spring Boot

Junit & AssertJ

package com.blog;

import org.junit.jupiter.api.*;

public class JUnitCycleTest {

    @BeforeAll // 전체 테스트 시작 전 1회 실행 (static으로 선언)
    static void beforeAll(){
        // DB 연결이나 테스트 환경 초기화할 때 사용
        System.out.println("@BeforeAll");
    }

    @BeforeEach // 테스트 케이스 시작 전마다 실행
    public void beforeEach(){
        // 메서드에 사용되는 객체 초기화하거나 미리 필요한 값을 넣는 경우 사용
        System.out.println("@BeforeEach");
    }

    @Test
    public void test1(){
        System.out.println("test1");
    }

    @Test
    public void test2(){
        System.out.println("test2");
    }
    @Test
    public void test3(){
        System.out.println("test3");
    }

    @AfterAll // 전체 테스트 후 종료 전 1회 실행(static)
    static void afterAll(){
        // DB연결종료나 공통으로 사용하는 자원 해제
        System.out.println("@AfterAll");
    }

    @AfterEach //테스트 종료 전마다 실행
    public void afterEach(){
        //테스트 이후 특정 데이터 삭제
        System.out.println("@AfterEach");
    }
}

 

*컨트롤러 테스트 하는 방법

 

package com.blog.controller;

import com.blog.entity.Member;
import com.blog.service.TestService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class TestController {
    private final TestService testService;

    @GetMapping("/test")
    public List<Member> getAllMembers(){
        List<Member> members = testService.getAllMembers();
        return members;
    }

}

 

위의 컨트롤러를 테스트해보겠습니다 :)

 

package com.blog.controller;

import com.blog.entity.Member;
import com.blog.repository.MemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@SpringBootTest
@AutoConfigureMockMvc
class TestControllerTest {

    @Autowired protected MockMvc mockMvc; // 컨트롤러 테스트할 때 사용됨
    @Autowired private WebApplicationContext context;

    @Autowired
    private MemberRepository memberRepository;

    @BeforeEach
    public void mockMvcSetUp(){
        this.mockMvc = webAppContextSetup(context)
                .build();
    }
    @AfterEach
    public void cleanUp(){
        memberRepository.deleteAll();
    }

    @DisplayName("getAllMembers : 아티클 조회에 성공한다.")
    @Test
    public void getAllMembers() throws Exception{
        //given
        final String url = "/test";
        Member savedMember = memberRepository.save(new Member(1L,"홍길동"));

        // when
        // MockMvcRequestBuilders.get;
        final ResultActions result = mockMvc.perform(get(url) //요청 전송
                .accept(MediaType.APPLICATION_JSON)); //JSON으로 받겠다고 명시
        // ResultActions는 반환값을 가지고 이것을 .andExpect()로 응답검증
        // then
        result
                .andExpect(status().isOk())
                // servlet.result.MockMvcResultMatchers.jsonPath; JSON응답값을 가져온다. 0번째 배열에 들어있는 객체의 id값 가져옴
                .andExpect(jsonPath("$[0].id").value(savedMember.getId()))
                .andExpect(jsonPath("$[0].name").value(savedMember.getName()));
    }


}

 

리턴값이 리스트가 아닌 경우 바로 jsonPath("$.필드명") 으로 접근이 가능합니다.

ex. ResponseEntity<ArticleDto>

 

@DisplayName("findArticle: 블로그 글 조회에 성공한다.")
@Test
public void findArticle() throws Exception {
    // given
    final String url = "/api/articles/{id}";
    final String title = "title";
    final String content = "content";

    Article savedArticle = blogRepository.save(Article.builder()
            .title(title)
            .content(content)
            .build());
    // when
    final ResultActions resultActions = mockMvc.perform(get(url, savedArticle.getId()));

    // then
    resultActions.andExpect(status().isOk())
            .andExpect(jsonPath("$.content").value(content))
            .andExpect(jsonPath("$.title").value(title));
}

 


JSON값을 보내는 update기능의 경우 테스트 하는 법

@Autowired protected MockMvc mockMvc;

//직렬화 역직렬화를 위한 클래스, 자바객체 <->JSON 데이터
@Autowired protected ObjectMapper objectMapper;

//스프링컨테이너의 한 형태. applicationContext에 웹 환경에 필요한 기능을 추가한 것.
@Autowired private WebApplicationContext context;

@Autowired
BlogRepository blogRepository;
ResultActions result = mockMvc.perform(put(url, savedArticle.getId())
        // JSON 데이터를 보내요
        .contentType(MediaType.APPLICATION_JSON_VALUE)
        .content(objectMapper.writeValueAsString(request)));

// then
result.andExpect(status().isOk());

 

 


테스트 코드를 만들때 아래 코드로 테스트 준비를 해주면 좋을 것 같다. 참고하자

 


@SpringBootTest
@AutoConfigureMockMvc
class BlogApiControllerTest {

    @Autowired protected MockMvc mockMvc;

    //직렬화 역직렬화를 위한 클래스, 자바객체 <->JSON 데이터
    @Autowired protected ObjectMapper objectMapper;

    //스프링컨테이너의 한 형태. applicationContext에 웹 환경에 필요한 기능을 추가한 것.
    @Autowired private WebApplicationContext context;

    @Autowired
    BlogRepository blogRepository;

    @BeforeEach
    public void mockMvcSetUp(){
        //WebApplicationContext를 사용해서 mockMvc를 설정
        this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .build();
        blogRepository.deleteAll();
    }

 

 


예외 테스트하기

 

@DisplayName("중복회원으로 가입")
@Test
public void duplicatedMember() throws Exception {
    // given
    MemberVO testMember1 = MemberVO.builder().name("test1").password("1234").build();
    MemberVO testMember2 = MemberVO.builder().name("test1").password("1234").build();

    // when
    memberService.join(testMember1);


    // then
    assertThrows(IllegalArgumentException.class, () -> {
        memberService.join(testMember2);
    });

}

 

 

assertThrows 내에서 검증하고 싶은 함수 호출.

 

// then
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
    memberService.join(testMember2);
});
assertEquals("이미 존재하는 회원입니다.",exception.getMessage());

 

이렇게 예외 발생시 예외 메세지도 테스트할 수 있다.


 

https://github.com/shinsunyoung/springboot-developer/blob/main/chapter4/src/test/java/me/shinsunyoung/springbootdeveloper/TestControllerTest.java

 

본 포스팅은[스프링부트 3 백엔드 개발자되기: 자바 편] 을 참고하였습니다.

'Java > Spring Boot' 카테고리의 다른 글

SPRING SECURITY with JWT  (1) 2023.12.05
Thymeleaf 기본  (0) 2023.12.04
Thymeleaf 경로 설정하기  (0) 2023.11.30
spring security에서 @PreAuthorize가 안먹힐때 (SpringBoot 3.0 이상)  (0) 2023.11.27
쿼리 파라미터찍기  (0) 2023.11.08