Java - TestCode

mil nil·2023년 1월 30일
0

TIL (Today I Learned)

목록 보기
57/74

Test

F.I.R.S.T 원칙

  • Fast : 빨라야 한다.
  • Independent: 독립적이어야 한다.
  • Repeatable: 반복 가능해야한다.
  • Self-validating: 자체적으로 테스트 결과가 도출되야한다. (개발자가 print 찍어서 비교하는게 아니고 자동으로 수행되며 성공/실패 의 결과가 나오는 것)
  • Timely: 단위 테스트는 실제 코드보다 먼저 구현해야한다. (TDD일 경우에만 해당)

Given-When-Then 패턴

  • Given: 테스트에 필요한 및 Mock 객체를 통해 특정 상황에 대한 행동을 정의
  • When: 실제 테스트를 하는 메소드가 호출되며 테스트를 통한 결과값을 가져옴
  • Then: When 단계에서 나온 결과값을 검증

JUnit + Mockito

  • JUnit : Java 에서 사용되는 대표적인 테스트 프레임워크. 자바 개발자 93% 가 사용한다는 통계가 있습니다.
  • Mockito: Mock(가짜) 객체를 쉽게 만들고, 관리하고, 검증할 수 있는 방법을 제공하는 프레임워크. Mock 객체는 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 행동을 관리하는 객체
  • @Mock: Mock 객체를 만들어 반환해주는 어노테이션
  • @Spy: 원본 메소드 그대로 사용하는 어노테이션
  • @InjectMocks: @Mock 또는 @Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션
@Mock // 가짜 개체로 만들 것
private UserRepository userRepository;

@InjectMocks // 주입되는 곳 지정
private UserService userService;

@BeforeEach // 테스트 마다 직전에 한 번씩 반복되는 메소드
void prepare() {
	ReflectionTestUtils.setField(jwtUtil,
    	"secretKey", // jwtUtil의 secretKey값이 저장될 변수
        "7ZWt7ZW0OTntmZTsnbTtjIXtlZzqta3snYTrhIjrqLjshLjqs4TroZzrgpjslYTqsIDsnpDtm4zrpa3tlZzqsJzrsJzsnpDrpbzrp4zrk6TslrTqsIDsnpA="); // secretKey의 값
    jwtUtil.init(); // jwtUtil에서 @PostConstructor가 동작하지 않기 때문에, 임의로 실행시켜야 함
    }

@Spy // 원본 그대로 사용하기 원하는 개체
private JwtUtil jwtUtil;

JUnit의 생명 주기

  • @BeforeAll: 테스트를 시작하기 전에 호출되는 메서드
  • @BeforeEach: 각 테스트 메서드가 실행되기 전에 동작하는 메서드
  • @AfterAll: 테스트를 종료하면서 호출되는 메서드
  • @AfterEach: 각 테스트 메서드가 종료되면서 호출되는 메서드

Service

@Test
@DisplayName("회원 가입")
void signup() {
    // given
    SignupRequest request = SignupRequest.builder()
            .admin(false)
            .username("nathan")
            .password("1234qwer")
            .email("nathan@gmail.com")
            .build();

	when(userRepository.findByUsername(any(String.class)))
                .thenReturn(Optional.empty()); // repository에서 받아올 값 지정

	// when
    ResponseStatusDto response = userService.signup(request);

	// then
   	// 코드 확인
    assertThat(response.getStatusCode()).isEqualTo(StatusEnum.SIGN_SUCCESS.getStatusCode());
   	// 메시지 확인
   assertThat(response.getMsg()).isEqualTo(StatusEnum.SIGN_SUCCESS.getMsg());
    }

Controller

mockMvc를 활용해 Controller가 Mvc에서 데이터를 받아오는 것처럼 테스트 가능

@BeforeEach // 테스트 이전에 한 번씩 진행
public void init() { // mockMvc를 적용
	mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}

@Test
@DisplayName("회원가입 (성공)")
void signup() throws Exception {
	// given
    SignupRequest request = SignupRequest.builder()
    		.admin(false)
            .username("nathan")
            .password("1234qwer")
            .email("nathan@gmail.com")
            .build();

	ResponseStatusDto response = new ResponseStatusDto(StatusEnum.SIGN_SUCCESS);

	when(userService.signup(any(SignupRequest.class)))
    		.thenReturn(response);

	// when
    //API를 기준으로 테스트
    ResultActions resultActions = mockMvc.perform(
    	MockMvcRequestBuilders.post("/api/users/signup")    
        	.contentType(MediaType.APPLICATION_JSON)
            .content(new Gson().toJson(request))); //Json 형식으로 변형

	// then
    resultActions.andExpect(status().isOk())
    		.andExpect(jsonPath("statusCode", response.getStatusCode()).exists())
        	.andExpect(jsonPath("msg", response.getMsg()).exists());
    }

Repository

@Autowired // 연결만 하고 사용
private UserRepository userRepository; // repository는 DB에 다녀와야 한다.

@Test
@DisplayName("사용자 추가")
void addUser() {
	// given
    User user = new User(
    	"nathan",
        "1234qwer",
        "nathan@gmail.com",
        UserRoleEnum.USER
    );

	// when
    User saveUser = userRepository.save(user);

	// then
    assertThat(saveUser.getUsername()).isEqualTo(user.getUsername());
}

gson 사용하기 위해서 아래 의존성에 추가 -> json형식으로 바꿀 수 있게 도와줌

testImplementation 'com.googles.code.gson:2.9.0'
profile
자바 배우는 사람

0개의 댓글