본문 바로가기
Framework/Spring

Spring 공부내용 정리 : 1. 테스트 코드

by Cs.Woo 2021. 7. 25.

  해당 내용의 출처는 김영한 님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술의 강의 내용이고,본 포스트는 수강후 개인적으로 공부한 내용을 필기하고 다시 복습하기 위하여 작성된 것임을 밝힌다.

테스트 코드

  • 코드를 구현하였다면 , 해당 코드들이 제대로 작동되고 있는지에 대한 확인을하여야 한다. 실무에서는 test code를 이용하여 검증을 진행하는데 내용은 하기와 같다.
  • 개발한 기능을 실행해서 테스트 할 때 자바의 main메서드를 통해서 실행하거나, 웹 애플리케이션의 컨트롤러를 통해서 해당 기능을 실행한다.
  • 그러나 이러한 방법은 준비하고 실행하는데에 시간이 오래걸리고, 반복실행하기 어렵고 여러 테스트를 한번에 실행하기 어렵다는 단점이 있다.
  • 자바는 JUnit이라는 프레임워크로서 테스트를 실행하여 이러한 문제를 해결할 수 있다. 해당 내용 하기와 같다.
  • 테스트를 하기 위해서는 테스트 하고자 하는 구현체를 src/test/java 하위 디렉토리에 구현체를 생성해야한다.

// test를 돌려보는 클래스는 클래스명 뒤에 Test를 붙이는 것이 관례이다.
class MemoryMemberRepositoryTest {

    // 테스트 하고자 하는 클래스를 인스턴스화 한다.
    MemberRepository repository = new MemoryMemberRepository();

    // 테스트를 위해서는 Test라는 어노테이션을 사용하면 된다.
    // Junit이라는 프레임워크를 이용한 테스트인데 하기 코드와 같다.
    @Test
    public void save() {
        // 테스트를 위하여 맴버 객체를 새로 생성한다.
        Member member = new Member();
        // 생성된 객체에 name을 세팅한다
        member.setName("김민수");

        // respository 의  store에 member객체를 저장한다.
        repository.save(member);

        // repository의 findById로 방금 저장한 맴버 객체를 id로서 찾아온 뒤 result변수에 할당한다
        Member result  = repository.findById(member.getId()).get();

        // reulst와 member가 같다면 옳게 작동한 것이므로 참을 리턴하고 그렇지 않으면
        // false를 리턴하게 되기 때문에 검증할 수 있게 된다.
        // System.out.println("result : " + (member == result));
        // 매번 글자로 볼 수 없기 때문에 Assertions 라는 기능을 사용한다.
        // 앞의 인자 member가 모든 메소드를 통하여 같은 값이 도출되었는지를
        // 확인하는 메소드이다.
        Assertions.assertEquals(member, result);
    }


}
  • 테스트에 성공하면 녹색불이 들어오며 테스트에 성공하였다는 알림이 뜨지만, 하기의 assertEaquals에서 고의적으로 실패하는 값을 준다면 하기와 같은 에러를 볼 수 있다.
org.opentest4j.AssertionFailedError: 
Expected :Member(id=1, name=김민수)
Actual   :null
<Click to see difference>
  • 최근에는 상기와 같은 방법 외에 다른 방법도 사용되는데 다음과 같다.

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

        // assertJ를 이용한 예제
        assertThat(member).isEqualTo(result);
        // 쥬피터와 같이, member의 값이 result의 값과 같은지를 판별하는 메소드이다.
        // 스태틱 임포트도 가능하다.
  • 여러가지 테스트 케이스를 구현한다음 같이 테스트를 한다면, 테스트 메소드가 간섭이 발생하여, 옳은 코드임에도 불구하고 오류가 검증될 수 있다.
  • 따라서 하기의 내용을 진행하여 그것을 방지하여야 한다.

// MemoryMembeRepository

  public void clearStore() {
        store.clear();
    }

// TEST CODE

// 테스트는 메소드의 정의 순서와 상관없이 실행된다. 그리고 같은 객체를 공유해서 사용하기때문에
    // 테스트간 간섭이발생할 수 있다. 따라서 하나의 테스트가 끝나면 이전의 테스트 내용은 비워주어야 한다.
    // 그것을 구현하기 위한 것이 바로 afterEach 메소드이다.

    // 하나의 메소드가 테스트가 끝날때마다 깔끔하게 비워져야 다른 메소드의 테스트가
    // 원활하게 이루어지 진다. 따라서 해당하는 기능을 구현해주어야 되는데 다음과 같다.
    @AfterEach
    public void afterEach() {
        // 상기 AfterEach 메소드는 forEach와 비슷한 맥락이다.
        // 클래스 내부에 있는 메소드들을 하나씩 실행한 후 afterEach메소드가 실행되고 그 다음 메소드가
        // 실행이 된다.

        repository.clearStore();

    }
  • 이렇게 로직을 전부 구현하고 난 뒤, 테스트를 진행하는 것은 매우 중요하다. 그런데 여기에서 먼저 테스트를 진행한 다음, 테스트 케이스를 통과한 코드를 프로젝트에 적용하는 방법도 존재한다 이것을 테스트 주도 개발 TDD라고 일컫는다.