본문 바로가기
테스트/테스트코드

Service Test 작성 방법 및 예시

by 문자메일 2023. 8. 15.

UserService에서는 로그인과 회원가입기능 처리하는 메서드가 구현되어 있는 상태이다.

UserService

-join

-login

 

이전에 Controller 에서는 Exception 발생하여 HttpStatus 에러 코드가 사용자가 정의한대로 왔는지를 체크하였고, Service단에서 현재 로직에서는 회원가입, 로그인 성공 / 예외로 인한 실패(exception) 만 존재하므로,  

when() mocking 메서드로 발생할 수 있는 상황 경우의 수에 따른 케이스를 테스트코드에 정의하고, 각 경우의 수에 따라 발생하는 결과 확인하는 검증 코드 넣어서 테스트 작성한다.

Assertions.assertDoesNotThrow(()->userService.join(userName, password));

 

SnsApplicationException e = Assertions.assertThrows(SnsApplicationException.class, ()->userService.join(userName, password));
Assertions.assertEquals(ErrorCode.DUPLICATED_USER_NAME, e.getErrorCode());

 

 

 

아래는 UserService의 테스트 작성 예시 코드이다.

package com.example.sns.service;

import com.example.sns.exception.ErrorCode;
import com.example.sns.exception.SnsApplicationException;
import com.example.sns.fixture.UserEntityFixture;
import com.example.sns.model.entity.UserEntity;
import com.example.sns.repository.UserEntityRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.Optional;

import static org.mockito.Mockito.when;

@SpringBootTest
public class UserServiceTest{

    @Autowired
    private UserService userService;

    @MockBean
    private UserEntityRepository userEntityRepository;

    @MockBean
    private BCryptPasswordEncoder encoder;

    // 회원가입 성공
    @Test
    void 회원가입_성공(){
        String userName = "userName";
        String password = "password";

        // 동일 userName 회원 존재하지 않음
        when(userEntityRepository.findByUserName(userName)).thenReturn(Optional.empty());

        // save() 어떤 파라메터로든 호출 시 사용자가 정의한 UserEntity return하도록 정의
        when(userEntityRepository.save(Mockito.any())).thenReturn(UserEntityFixture.get(userName, password));

        Assertions.assertDoesNotThrow(()->userService.join(userName, password));
    }

    // 회원가입 실패 이미 존재하는 계정명
    @Test
    void 회원가입_실패_이미_존재하는_계정명(){
        String userName = "userName";
        String password = "password";

        UserEntity fixture = UserEntityFixture.get(userName, password);

        // 동일 userName 회원 존재함
        when(userEntityRepository.findByUserName(userName)).thenReturn(Optional.of(fixture));

        // save() 어떤 파라메터로든 호출 시 사용자가 정의한 UserEntity return하도록 정의
        when(userEntityRepository.save(Mockito.any())).thenReturn(Optional.of(fixture));

        SnsApplicationException e = Assertions.assertThrows(SnsApplicationException.class, ()->userService.join(userName, password));
        Assertions.assertEquals(ErrorCode.DUPLICATED_USER_NAME, e.getErrorCode());
    }

    // 로그인 성공
    @Test
    void 로그인_성공(){
        String userName = "userName";
        String password = "password";

        UserEntity fixture = UserEntityFixture.get(userName, password);

        // 회원가입 되어 있을 때
        when(userEntityRepository.findByUserName(userName)).thenReturn(Optional.of(fixture));

        // 비밀번호가 일치할 때
        when(encoder.matches(password, fixture.getPassword())).thenReturn(true);

        Assertions.assertDoesNotThrow(()->userService.login(userName,password));
    }

    // 로그인 실패 존재하지 않는 회원
    @Test
    void 로그인_실패_존재하지_않는_회원(){
        String userName = "userName";
        String password = "password";

        UserEntity fixture = UserEntityFixture.get(userName, password);

        // 회원가입 되어 있을 때
        when(userEntityRepository.findByUserName(userName)).thenReturn(Optional.empty());
        
//        // 비밀번호가 일치할 때, 아래 mock 주석해놓으면 라이브러리에서 정의 안 된 mock message는 false 리턴하는 것 확인하였음
//        when(encoder.matches(password, fixture.getPassword())).thenReturn(true);

        SnsApplicationException e = Assertions.assertThrows(SnsApplicationException.class, ()->userService.login(userName,password));
        Assertions.assertEquals(HttpStatus.NOT_FOUND, e.getErrorCode().getStatus());
    }

    // 로그인 실패 비밀번호가 틀린 경우
    @Test
    void 로그인_실패_비밀번호가_틀린_경우(){
        String userName = "userName";
        String password = "password";

        UserEntity fixture = UserEntityFixture.get(userName, password);

        // 회원가입 되어 있을 때
        when(userEntityRepository.findByUserName(userName)).thenReturn(Optional.of(fixture));

        // 비밀번호가 일치할 때
        when(encoder.matches(password, fixture.getPassword())).thenReturn(false);

        SnsApplicationException e = Assertions.assertThrows(SnsApplicationException.class, ()->userService.login(userName,password));
        Assertions.assertEquals(HttpStatus.UNAUTHORIZED, e.getErrorCode().getStatus());
    }
}

댓글