[Spring] Service 단위 테스트

maxxyoung·2022년 10월 28일
0

Service

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;
    private final FileService fileService;
    private final FileDBService fileDBService;
    private final EncryptAlgorithm encryptAlgorithm;

    @Override
    public Optional<Member> login(String id, String password) throws EncryptAlgorithmFailException {
        return memberRepository.findMemberByPasswordAndId(id, encryptAlgorithm.encrypt(password));
    }

    @Override
    @Transactional
    public Member register(MemberRegisterForm memberRegisterForm, MultipartFile profileFile) throws IOException {

        Member member = createMember(memberRegisterForm);

        if(FileUtil.doesFileExist(profileFile)){
            UploadFile uploadFile = fileService.storeFile(profileFile, member);
            member.setUploadFile(uploadFile);
        }

        return memberRepository.save(member);
    }
}

...

Service Test Code

로그인과 회원 등록에 관한 테스트 코드 작성

@ExtendWith(MockitoExtension.class) //mock 객체 사
class MemberServiceImplTest {

    @InjectMocks
    private MemberServiceImpl memberService;

    @Mock
    private MemberRepository memberRepository;

    private static MockedStatic<FileUtil> fileUtil;

    @Spy
    private SHA256 encryptAlgorithm;

    @BeforeAll
    public static void beforeAll(){
        fileUtil = mockStatic(FileUtil.class);
    }

    @AfterAll
    public static void afterAll(){
        fileUtil.close();
    }


    @Test
    public void 회원가입_성공_프로필사진_없음() throws Exception{
        //given
        String id = "choi1234";
        String password = "1234";
        String nickname = "maxx";


        MemberRegisterForm memberRegisterForm = new MemberRegisterForm();
        memberRegisterForm.setId(id);
        memberRegisterForm.setNickname(nickname);
        memberRegisterForm.setPassword(password);

        doReturn(new Member("M123456789", id, nickname, encryptAlgorithm.encrypt("1234"))).when(memberRepository).save(any(Member.class));
        when(FileUtil.doesFileExist(any(MultipartFile.class))).thenReturn(false);

        //when
        Member registeredMember = memberService.register(memberRegisterForm, any(MultipartFile.class));

        //then
        assertThat(memberRegisterForm.getId()).isEqualTo(registeredMember.getId());
        assertThat(memberRegisterForm.getNickname()).isEqualTo(registeredMember.getNickname());
        assertThat(encryptAlgorithm.encrypt(memberRegisterForm.getPassword())).isEqualTo(registeredMember.getPassword());

    }
    
    @Test
    public void 회원가입_성공_프로필사진_있음() throws Exception{
        //given
        String id = "choi1234";
        String password = "1234";
        String nickname = "maxx";


        MemberRegisterForm memberRegisterForm = new MemberRegisterForm();
        memberRegisterForm.setId(id);
        memberRegisterForm.setNickname(nickname);
        memberRegisterForm.setPassword(password);


        //MultipartFile mock
        MultipartFile multipartFile = new MockMultipartFile("file"
                                                            , "test.png"
                                                            , "img/png"
                                                            , new FileInputStream("/Users/choidayoung/dev/file/before/test.png"));
        UploadFile uploadFile = new UploadFile(123456789L, id, "eedx-3343-48c83-3jdj.png", "/Users/choidayoung/dev/file/profile/dev", "test.png");
//        doReturn(uploadFile).when(fileService).storeFile(any(MultipartFile.class), any(Member.class));
        Member member = new Member("M123456789", id, nickname, encryptAlgorithm.encrypt(password));
        member.setUploadFile(uploadFile);
        doReturn(member).when(memberRepository).save(any(Member.class));

        //when
        Member registeredMember = memberService.register(memberRegisterForm, multipartFile);

        //then
        assertThat(memberRegisterForm.getId()).isEqualTo(registeredMember.getId());
        assertThat(memberRegisterForm.getNickname()).isEqualTo(registeredMember.getNickname());
        assertThat(encryptAlgorithm.encrypt(memberRegisterForm.getPassword())).isEqualTo(registeredMember.getPassword());
        assertThat(registeredMember.getUploadFile().getId()).isNotNull();
        assertThat(registeredMember.getUploadFile().getLocalFileName()).isNotEmpty();
    
    }

    @Test
    public void 로그인_성공() throws Exception{
        //given
        String id = "choi1234";
        String password = "1234";
        String encryptPassword = encryptAlgorithm.encrypt(password);

        Member member = new Member("M123456789", encryptPassword, "maxx", id);
        doReturn(Optional.of(member)).when(memberRepository).findMemberByPasswordAndId(id, encryptPassword);

        //when
        Optional<Member> loginMember = memberService.login(id, password);

        //then
        assertThat(loginMember.get().getMemberId()).isEqualTo(member.getMemberId());
        assertThat(loginMember.get().getNickname()).isEqualTo(member.getNickname());
    }

}

테스트를 하는 데 가장 메인이 되는 클래스인 MemberService는 @InjectMocks 해주고, 나머지 클래스들은 @Mock 처리. 비밀번호 암호화 클래스는 진짜 사용해야하므로 @Spy 처리 해줌.

static method의 경우 stub하려면 3.0.0 이상의'org.mockito:mockito-inline' 라이브러리가 필요했음

private static MockedStatic<FileUtil> fileUtil;

@BeforeAll
    public static void beforeAll(){
        fileUtil = mockStatic(FileUtil.class);
    }

@AfterAll
    public static void afterAll(){
        fileUtil.close();
    }
    
when(FileUtil.doesFileExist(any(MultipartFile.class))).thenReturn(false);    

이렇게 구성하면 stub을 할 수 있음

chaining method mock 객체 삽입하려면

A.getB().getId();

순서 중요!

when(B.getId()).thenReturn(123456L);
when(A.getB()).thenReturn(B);

이렇게 오른쪽에서 왼쪽으로 객체를 stub해주어야 함

profile
오직 나만을 위한 글. 틀린 부분 말씀해 주시면 감사드립니다.

0개의 댓글