Given-When-Then


Given-When-Then 패턴은 테스트 코드를 표현하는 방식 중 하나입니다. 단어에서 유추할 수 있듯이 다음과 같은 단계를 설정해서 각 단계의 목적에 맞게 코드를 작성합니다.

  1. Given

    테스트를 수행하기 전에 테스트에 필요한 환경을 설정하는 단계입니다. 테스트에 필요한 변수를 정의하거나 Mock객체를 통해 특정 상황에 대한 행동을 정의합니다.

  2. When

    테스트의 목적을 보여주는 단계입니다. 실제 테스트 코드가 포함되며, 테스트를 통한 결괏값을 가져오게 됩니다.

  3. Then

    테스트의 결과를 검증하는 단계입니다. 일반적으로 When 단계에서 나온 결괏값을 검증하는 작업을 수행합니다. 결괏값이 아니더라도 이 테스트를 통해 나온 결과에서 검증해야 하는 부분이 있다면 이 단계에 포함합니다.


F.I.R.S.T


F.I.R.S.T는 테스트 코드를 작성하는 데 도움이 될 수 있는 5가지 규칙을 의미합니다. 이 규칙은 대체로 단위 테스트에 적용할 수 있는 규칙이며, 간단하게 설명하면 다음과 같습니다.

  1. Fast

    테스트는 빠르게 수행되어야 합니다. 테스트가 느리면 코드를 개선하는 작업이 느려져 코드 품질이 떨어질 수 있습니다. 테스트 속도에 절대적인 기준은 없지만 목적을 단순하게 설정해서 작성하거나 외부 환경을 사용하지 않는 단위 테스트를 작성하는 것 등을 빠른 테스트라고 할 수 있습니다.

  2. Isolation

    하나의 테스트 코드는 목적으로 여기는 하나의 대상에 대해서만 수행되어야 합니다. 만약 하나의 테스트가 다른 테스트 코드와 상호작용하거나 관리할 수 없는 외부 소스를 사용하게 되면 외부 요인으로 인해 테스트가 수행되지 않을 수 있습니다.

  3. Repeatable

    테스트는 어떤 환경에서도 반복 가능하도록 작성해야 합니다. 이 의미는 앞의 Isolation 규칙과 비슷한 의미를 가지고 있습니다. 테스트는 개발 환경의 변화나 네트워크의 연결 여부와 상관없이 수행되어야 합니다.

  4. Self-Validation

    테스트는 그 자체만으로도 테스트의 검증이 완료되어야 합니다. 테스트가 성공했는지 실패했는지 확인할 수 있는 코드를 함께 작성해야 합니다. 만약 결괏값과 기댓값을 비교하는 작업을 코드가 아니라 개발자가 직접 확인하고 있다면 좋지 못한 테스트 코드입니다.

  5. Timely

    테스트 코드는 테스트하려는 애플리케이션 코드를 구현하기 전에 완성되어야 합니다.
    너무 늦게 작성된 테스트 코드는 정상적인 역활을 수행하기 어려울 수 있습니다. 또한 테스트 코드로 인해 발견된 문제를 해결하기 위해 소모되는 개발 비용도 커지기 쉽습니다. 다만 이 개념은 테스트 주도 개발을 따르는 테스트 작성 규칙으로, 테스트 주도 개발을 기반으로 애플리케이션을 개발하는 것이 아니라면 이 규칙은 제외하고 진행하기도 합니다.


Junit


  • 단위 테스트(Unit Test)를 위한 도구를 제공
  • Junit5는 크게 Jupiter, Platform, Vintage의 세 모듈로 구성됩니다.
  • Jupiter : Junit 5에서 제공하는 Jupiter 기반의 테스트를 실행하기 위한 테스트 엔진을 가지고 있다.
  • Vintage : Junit 3, 4에서 제공하는 Jupiter 기반의 테스트를 실행하기 위한 테스트 엔진을 가지고 있다.
  • Platform : 테스트를 실행하기 위한 뼈대
    테스트를 발견하고 테스트 계획을 생성하는 테스트 엔진의 인터페이스를 가지고 있다. 테스트 엔진은 테스트를 발견하고 테스트를 수행하며, 그 결과를 보고하는 역활을 수행한다.

Junit의 생명주기



Junit Main Annotation


@SpringBootTest

  • 통합 테스트 용도로 사용됨
  • @SpringBootApplication을 찾아가 하위의 모든 Bean을 스캔하여 로드함
  • 그 후 Test용 Application Context를 만들어 Bean을 추가하고, MockBean을 찾아 교체

@ExtendWith

  • @ExtendWith는 메인으로 실행될 Class를 지정할 수 있음
  • @SpringBootTest는 기본적으로 @ExtendWith가 추가되어 있음

@WebMvcTest(Class명.class)

  • ()에 작성된 클래스만 실제로 로드하여 테스트를 진행
  • 매게변수를 지정해주지 않으면 @Controller, @RestController, @RestControllerAdvice등 컨드롤러와 연관된 Bean이 모두 로드됨

@Autowired about Mockbean

  • Controller의 API를 테스트하는 용도인 MockMvc 객체를 주입 받음
  • perform() 메소드를 활용하여 컨트롤러의 동작을 확인할 수 있음
  • andExpect(), andDo(), andReturn()등의 메소드를 같이 활용함

@MockBean

  • 테스트할 클래스에서 주입 받고 있는 객체에 대해 가짜 객체를 생성해주는 어노테이션
  • 해당 객체는 실제 행위를 하지 않음
  • given() 메소드를 활용하여 가짜 객체의 동작에 대해 정의하여 사용할 수 있음

@AutoConfigureMockMvc

  • Spring.test.mockmvc의 설정을 로드하면서 MockMvc의 의존성을 자동으로 주입
  • MockMvc 클래스는 REST API 테스트를 할 수 있는 클래스

@Import

  • 필요한 Class들을 Configuration으로 만들어 사용할 수 있음
  • Configuration Component 클래스도 의존성 설정할 수 있음
  • Import된 클래스는 주입으로 사용 가능

통합 테스트


통합 테스트는 여러 기능을 조합하여 전체 비즈니스 로직이 제대로 동작하는지 확인하는 것을 의미

통합 테스트의 경우, @SpringBootTest를 사용하여 진행

  • @SpringBootTest는 @SpringBootApplication을 찾아가서 모든 Bean을 로드하게 됨
  • 이 방법을 대규모 프로젝트에서 사용할 경우, 테스트를 실행할 때마다 모든 빈을 스캔하고 로드하는 작업이 반복되어 매번 무거운 작업을 수행해야 함

단위 테스트


단위 테스트는 프로젝트에 필요한 모든 기능에 대한 테스트를 각각 진행하는 것을 의미

일반적으로 스프링 부트에서는 'org.springframework.boot:spring-starter-test' 디펜던시만으로 의존성을 모두 가질 수 있음

0개의 댓글