본문 바로가기
우아한테크코스 4기/레벨1

[Java] @BeforeEach와 독립적인 단위 테스트

by 나는후니 2022. 4. 6.

테스트 코드를 작성하다보면 공통적으로 갖는 상태를 필드 변수로 선언하고 @BeforeEach 애노테이션을 사용하여 각 테스트가 실행 되기 전 필드 변수를 초기화 해줍니다.

테스트 메서드마다 상태를 초기화할 수 있어 독립적으로 테스트를 유지할 수 있고 테스트가 돌아가는 지점의 코드가 간결해져 많이 이용하곤 하는데요. 정말 BeforeEach를 사용하는 것이 좋은 점만 있을까요?

 

@BeforeEach의 사용으로 인해 발생하는 문제점을 알아보고 이 문제를 해결할 수 있는 방안에 대해 포스팅해보려합니다.

BeforeEach를 사용한 테스트코드

먼저 @BeforeEach를 사용하여 테스트 픽스처를 초기화하는 테스트를 간단하게 만들어봅시다.

class WalletTest {

    private Wallet wallet;

    @BeforeEach
    void setUp() {
        wallet = new Wallet();
        wallet.addMoney(10000);
    }

    @Test
    void addMoney() {
        wallet.addMoney(100);
        assertThat(wallet.getMoney()).isEqualTo(10100);
    }

    @Test
    void pay() {
        wallet.pay(1000);
        assertThat(wallet.getMoney()).isEqualTo(9000);
    }

    @Test
    void payException() {
        assertThatThrownBy(() -> wallet.pay(100000))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("돈이 부족합니다.");
    }
}

위 테스트 코드를 살펴보면 Wallet 객체를 BeforeEach로 초기화하여 매 테스트에서 활용하고 있습니다.
코드가 간단해 보인다는 장점은 있지만 과연 이 테스트가 독립적이라고 이야기 할 수 있을까요?

독립적인 테스트라면 테스트코드만으로 이해가 가능해야 한다.

addMoney 테스트를 잘라서 가져와보겠습니다.

이 테스트 코드만 보고 테스트의 의미를 이해할 수 있을까요?

이 테스트 클래스가 굉장히 복잡하고 BeforeEach라는 애노테이션을 보지 못한 개발자라면 아래와 같이 생각할 수 있을 것 같습니다.

  1. Wallet이라는 지갑에는 기본 10000원이 들어있나?
  2. 100원을 더했는데 왜 10100원이지? 다른 테스트를 살펴 봐야겠다.

위에서도 설명하듯 다른 테스트 메서드를 확인해야만 이 코드에 대한 이해가 가능합니다.

독립적인 테스트라면 다른 테스트에 영향을 주면 안된다.

Wallet의 요구사항으로 금액을 추가할 때는 10000원 미만만 가능하다. 하는 요구사항이 추가됐다고 가정하겠습니다.
setUp메서드에서는 금액 10000원을 추가하고 있기 때문에 내용을 조금 수정해보겠습니다.

10000원에서 9000원을 추가하는 것으로 변경됐다.

그리고 기존의 테스트 코드를 실행시켜보겠습니다.

예외 처리를 진행하는 부분만 테스트가 통과하고 나머지는 모두 실패합니다.

모든 테스트 코드가 setUp메서드의 코드를 강하게 알고 있기 때문에 이런 문제가 발생하는 것이죠.

요구사항이 하나 추가됐을 뿐인데 깨지는 테스트 코드를 모두 수정하기 위해 많은 비용이(여러 메서드를 수정) 발생하는 것을 체감할 수 있습니다.

독립적인 테스트 만들기

그렇다면 독립적인 테스트를 만들기 위해서는 어떻게 해야할까요?

정말 간단합니다. 테스트 픽스처를 BeforeEach로 셋업하지 말고 메서드를 하나 만들어 각 테스트 메서드에서 사용할 수 있게 만들어주면 됩니다.

테스트 픽스처를 각 테스트 메서드에서 생성하여 사용함으로써 완벽히 독립적인 테스트 코드가 되었습니다.

다시 addMoney 메서드를 보면 해당 메서드만 읽어도 쉽게 어떤 테스트 코드인지 알 수 있습니다.

정리

@BeforeEach의 사용이 오히려 독립적인 테스트 코드를 작성하는 것을 헤칠 수 있습니다. 적절한 테스트 픽스처를 만들어 사용한다면 훨씬 더 독립적인 테스트를 유지하는 데 도움이 될 수 있습니다!