본문 바로가기

뭐라도 공부해보자!!( 이론 )/Web

5. Spring/Spring Boot를 이용한 로그인 페이지 만들기 : 테스트

반응형

 시작에 앞서서 해당 실습은 인프런에서 제공되는 무료 강좌에서 다룬 실습입니다. 강좌를 진행하신 튜터 분의 설명을 듣고 싶다면 해당 강좌 링크를 남겨둘테니 들으시기를 바랍니다.(개인적으로는 한 번 듣는 것을 추천드립니다!!)

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard

 

[무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 이전 글을 보고 오시지 않았다면 한 번 보고 오시는 것을 추천드립니다. 테스트를 해야하는 데, 정작 테스트해야할 코드가 없다면 그 것 만큼 황당한 일은 없겠죠? 링크는 아래에 남겨 두겠습니다.

 

https://messy-developing-diary.tistory.com/52

 

3. Spring/Spring Boot를 이용한 로그인 페이지 만들기 : 로그인 페이지 관련 구조 설명

시작에 앞서서 해당 실습은 인프런에서 제공되는 무료 강좌에서 다룬 실습입니다. 강좌를 진행하신 튜터 분의 설명을 듣고 싶다면 해당 강좌 링크를 남겨둘테니 들으시기를 바랍니다.(개인적으

messy-developing-diary.tistory.com

 

 본격적으로 실습을 시작해보자. 우리는 우리가 작성한 코드가 제대로 작동하는 지 알고 싶다. 규모가 작은 프로그램이면 모든 코드를 작성한 후 테스트해도 문제가 발생하지 않겠지만, 규모가 일정 크기 이상이 되면 끊어가면서 테스트할 필요가 있다. 이번 실습에서는 JUnit을 이용하여 테스트를 진행할 것이다. 

 일단은 JUnit에 대해 간략하게나마 알 필요가 있다. 공식 사이트에 들어가 보면 JUnit에 대해서 이렇게 기술하고 있다.

 

The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the TestEngine API for developing a testing framework that runs on the platform.

 

 해석하자면 JVM 상에서 테스트 프레임워크를 런칭하기 위한 가장 기본이 되면서도, 동시에 테스트 엔진 관련 API를 제공하여 플랫폼 상에서 동작하는 프레임워크를 개발하는데 사용되기도 한다. IntelliJ, Eclipse 등 유명 IDE, Gradle, Maven, Ant은  JUnit Platform을 제공하고 있다.

 테스트 코드를 작성하는 방법에 대해 간단하게 알아보자. junit과 관련된 라이브러리를 클래스에 import해주고 @Test 어노테이션을 단 void 메서드에 테스트할 내용을 작성하면 된다. 다음은 공식  Junit 문서에서 발최한 코드이다.

 

import static org.junit.jupiter.api.Assertions.assertEquals;

import example.util.Calculator;

import org.junit.jupiter.api.Test;

class MyFirstJUnitJupiterTests {

    private final Calculator calculator = new Calculator();

    @Test
    void addition() {
        assertEquals(2, calculator.add(1, 1));
    }

}

 

 강의 튜터분께서 약간의 팁으로 테스트 케이스를 작성할 때, "When, What, Then"에 맞추어서 작성하면 파악이 쉽다고 하셨다. 경험적으로 잘 이해되는 글들이 육하원칙에 맞추어져서 써져있는 것과 같은 원리이다. 튜터분은 테스트 케이스를 간단하면 간단할 수록 잘 짜여진 코드일 확률이 높다고 하였다. 클래스 의존관계가 서로 독립적일 수록 관리가 편하기 때문이다. (추가적으로 아예 테스트 케이스를 미리 작성하고 그에 맞추어 개발을 하는 경우도 있다. 이러한 개발 방식을 TDD(Test Driven Development)라고 한다. )

 본격적으로 테스트 케이스를 작성해보자. 프로젝트에서  src 폴더 안에 test 폴더에다 테스트 케이스를 작성할 것이다. 관례적으로 test 폴더 안에서 패키지와 클래스의 이름을 짓는 방식이 있다. 패키지의 경우 해당 클래스가 main 폴더 안에서 속한 페키지 이름을 그대로 따라가고, 클래스의 이름은 테스트하고자 하는 클래스 명 + Test로 짓는 경우가 일반적이다. 우리는 일단 서비스 클래스와 관련된 테스트 케이스와 메모리 저장소와 관련된 테스트 케이스를 작성할 것이다. 코드는 다음과 같다.

 

package com.example.loginpage.repository;

import com.example.loginpage.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.*;

class MemoryMemberRepositoryTest {

    MemoryMemberRepository repository = new MemoryMemberRepository();

    @AfterEach
    public void afterEach(){
        repository.clearStore();
    }

    @Test
    void save() {
        //given
        Member member = new Member();
        member.setName("spring");

        //when
        repository.save(member);

        //then
        Member result = repository.findById(member.getId()).get();
        assertThat(result).isEqualTo(member);
    }

    @Test
    void findAll() {
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2= new Member();
        member2.setName("spring2");
        repository.save(member2);

        //when
        List<Member> result = repository.findAll();

        //then
        assertThat(result.size()).isEqualTo(2);
    }

    @Test
    void findByName() {
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2= new Member();
        member2.setName("spring2");
        repository.save(member2);

        //when
        Member result = repository.findByName("spring1").get();

        //then
        assertThat(result).isEqualTo(member1);
    }

}

 

package com.example.loginpage.service;

import com.example.loginpage.domain.Member;
import com.example.loginpage.repository.MemberRepository;
import com.example.loginpage.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

    @AfterEach
    public  void  afterEach(){
        memberRepository.clearStore();
    }

    @Test
    public void 회원가입(){
        //Given
        Member member = new Member();
        member.setName("hello");

        //When
        Long saveId = memberService.join(member);

        //The
        Member findMember = memberRepository.findById(saveId).get();
        assertEquals(member.getName(), findMember.getName());
    }

    @Test
    public void 중복_회원_예외(){
        //Given
        Member member1 = new Member();
        member1.setName("spring");
        Member member2 = new Member();
        member2.setName("spring");
        //When
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class,
                () -> memberService.join(member2));//예외가 발생해야 한다.

        //Then
        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
    }
}

 

 팁으로 인텔리제이에서는 테스트 케이스를 쉽게 작성할 수 있도록 기능을 제공한다. 테스트 케이스를 작성하고자 하는 클래스 이름을 선택하고 alt + Enter를 누르면 테스트 케이스를 만들 수 있는 옵션을 선택할 수 있다. 해당 옵션을 선택하여 테스트 코드를 만들면 자동으로 형식에 맞추어서 test 폴더 안에 패키지와 클래스를 생성한다. 

 코드에 아무런 이상이 없다면 ternminal에 제대로 테스트가 실행되었다고 뜨면서, 각 테스트 별로 걸린 시간이 나올 것이다. 만약 일부 테스트에 오류가 있다면, 그 테스트에 어떤 오류가 뜨는 지 콘솔 창에 뜰 것이다. (물론 당연하지면 예외 상황에 대해서 콘솔에 뜨게 하려면 이 부분 역시 프로그래머가 코드를 작성해 주어야 한다! )

 이렇게 테스트 코드를 작성해 보았다. 이 글에서 다룬 JUnit의 기능은 극히 일부에 불과하다. 나중에 기회가 되면 JUnit에 대해서는 별도로 자세하게 다루어 보는 것으로 하고, 이번 글은 여기서 마친다.

반응형