Basics: build, operate, check

  • 모든 통합테스트는 build, operate, check 단계를 가진다.
  • build: 테스트 시나리오를 준비하는 단계. 일반적으로 데이터에비스에 데이터를 추가한다.
  • operate: 테스트할 API나 객체의 메서드를 호출한다.
  • check: 실행한 API나 메서드의 결과가 예상한대로 동작했는지 확인한다.

build 단계: 데이터 추가

  • build 단계에 테스트 시나리오를 위해 데이터베이스에 데이터를 추가해야된다.
  • 데이터를 추가하는 방법으로는 3가지가 있다.
    • 테스트 중인 시스템의 API 호출
    • 순수 SQL 사용
    • Repository Layer 사용

테스트 중인 시스템의 API 호출

  • 이는 안티패턴이 될 수 있다.
  • build 단계에서 테스트 실패가 발생할 수 있다.
  • 테스트가 실패하면 build 단계에서 실패했는지, operate 단계에서 실패했는지 확인을 해봐야된다.
  • build 단계에서 호출한 API가 수정이 되었을 때, 이로인해 테스트가 실패로 바뀔 수 있다.

순수 SQL 사용

  • 테스트 중인 시스템의 API를 호출할 때 발생하던 문제는 해결된다.
  • 하지만, 프로덕트 코드에서 ORM을 사용하고 있다면, ORM에서 제공하는 기능을 모두 테스트 코드에서 구현해야된다.

Repository Layer 사용

  • ‘테스트 중인 시스템의 API 호출’ 과 비슷해보일 수 있지만, 애플리케이션 API를 호출하는 것이 아닌 Repository 레이어를 사용하는 방법이다.
  • 애플리케이션은 일반적으로 최소 2, 3개 레이어로 구성되는데 레이어가 추가될수록 버그가 발생할 확률이 높다.
  • DB와 가장 인접한 Repository Layer를 사용해서 버그가 발생할 확률을 낮출 수 있다.

build 단계: 엔티티 생성

  • 일반적으로 테스트 코드에서 엔티티를 생성할 때, 코드 중복을 막기 위해서 팩토리 메서드를 만들어서 호출한다.
    • 아래 코드에서 createDefaultcreateDefaultUserAccount가 팩토리 메서드다.
//BUILD  
Organization organization = createDefault();  
organizationRepository.save(organization);  
User user = createDefaultUserAccount(organization);  
userAccountRepository.save(organisation);

//OPERATE  
client.updateUserAccount(updateRequest);

//CHECK  
user = userAccountRepository.getUserAccount(user.getId());  
assertUser(updateRequest, user);
  • 하지만 팩토리 메서드는 문제점이 있다.
    • 테스트 케이스가 많아질수록 같은 엔티티에 대한 팩토리 메서드가 점점 늘어난다.
    • 팩토리 메서드가 위치해야 되는 곳에 대한 고민이 생긴다.
  • 빌더 패턴을 사용해서 이를 해결할 수 있다.

check 단계: Assertion