반응형

테스트 코드 작성 시 mocking을 위한 객체를 보통은 테스트 코드 아래에 private로 선언해서 사용한다.

이게 한두 개면 그냥 쓰는데 케이스가 다양하거나 테스트 양이 많아 테스트 객체를 생성하는 것만으로도 몇백 줄이 되게 되면 점점 테스트코드가 뭐고 객체가 뭔지 가독성을 잃게 된다.

그래서 보통 객체 생성부분을 다 발라서 별도 클래스를 두고 extend 해서 쓰곤 했었다.

class TournamentServiceTest extends TournamentServiceTestArguments {
..


//
public class TournamentServiceTestArguments {
  protected static TournamentRecordRequest getExistSearchValueTournamentRecordRequest(TournamentType tournamentType) {
    return TournamentRecordRequest.builder()
        .searchType(tournamentType)
        .searchValue(TEST_TOURNAMENT_NAME)
        .startDateTime(TEST_START_DATETIME)
        .endDateTime(TEST_END_DATETIME)
        .build();
  }
  ...
  }

오늘 타 회사 기술블로그 글을 읽다가 이걸 명칭한다는게 있다는걸 알고.. 기록해본다.

나만 고민한게 아니구나..ㅋㅋ

 

Object Mother

"Object Mother"는 소프트웨어 개발, 특히 테스트 코드 작성 시 자주 사용되는 디자인 패턴 중 하나. 이 패턴은 테스트에서 사용할 복잡한 객체 인스턴스를 생성하는 방법을 제공한다. 객체를 생성하는 로직을 별도의 클래스나 메서드로 분리하여 테스트 코드의 중복을 줄이고, 객체 생성에 관련된 코드의 가독성과 유지보수성을 높이는 것이 목적이다.

주요 특징:

  1. 객체 생성의 분리:
    • 테스트 코드에서 직접 객체를 생성하지 않고, Object Mother 클래스를 통해 필요한 객체를 생성한다.
    • 테스트 코드와 객체 생성 로직을 분리하여 테스트의 가독성을 높이고, 테스트에서 필요로 하는 객체를 일관되게 생성할 수 있다.
  2. 복잡한 객체 생성:
    • 기본적으로 생성자가 복잡하거나 여러 설정이 필요한 객체를 손쉽게 생성할 수 있도록 한다.
    • 객체의 기본 설정이나 상태를 지정하여, 테스트에서 필요한 특정 상태를 가진 객체를 제공할 수 있다.
  3. 테스트의 유지보수성 증가:
    • 객체 생성 로직이 한 곳에 모여 있어, 객체 생성 로직이 변경되더라도 한 곳에서만 수정을 하면 된다.
    • 테스트 코드에서 중복된 객체 생성 로직을 제거하여, 테스트 코드의 간결함과 유지보수성을 높다.
// User 클래스 예제
public class User {
    private String name;
    private int age;
    private String email;

    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // getter, setter 생략
}

// Object Mother 클래스
public class UserMother {
    public static User createDefaultUser() {
        return new User("John Doe", 30, "john.doe@example.com");
    }

    public static User createUserWithAge(int age) {
        return new User("John Doe", age, "john.doe@example.com");
    }

    public static User createUserWithName(String name) {
        return new User(name, 30, "john.doe@example.com");
    }

    // 다양한 생성 메서드 추가 가능
}

// 테스트 코드
public class UserTest {
    @Test
    public void testDefaultUser() {
        User user = UserMother.createDefaultUser();
        assertEquals("John Doe", user.getName());
        assertEquals(30, user.getAge());
    }

    @Test
    public void testUserWithSpecificAge() {
        User user = UserMother.createUserWithAge(25);
        assertEquals(25, user.getAge());
    }
}

장점:

  • 객체 생성 코드의 중복 제거.
  • 테스트 코드의 가독성 및 유지보수성 향상.
  • 다양한 상태를 가지는 테스트 객체를 쉽게 생성 가능.

단점:

  • Object Mother 클래스가 복잡해질 수 있음.
  • 여러 테스트에서 사용될 경우, 특정 테스트에 의존적인 설정이 들어갈 수 있음.

이 패턴은 주로 테스트 코드에서 객체 생성이 자주 필요하거나 복잡할 때 사용되며, 객체의 일관된 상태를 보장하고 중복 코드를 줄이는 데 도움을 준다.

++ 랜덤한 값을 생성하기 위한 라이브러리도 있다.

Naver에서 관리하고 있는 FixtureMonkey도 있지만 쓰기 편하고 효율적인 프로젝트로 알려진 EasyRandom도 있다.
EasyRandom은 github star 수도 가장 많았고, 이름 값 하는 프로젝트다.

EasyRandom은 굉장히 강력한데 다음과 같은 특징들이 있다.

  1. setter가 없어도 된다.
  2. contructor가 없어도 된다. (private contructor only인 경우)
  3. 자동으로 sub class들의 값도 random하게 채워준다.
  4. test object list 생성이 간단하다.

setter와 constructor가 없어도 된다는 점이 굉장히 좋아보인다! 조만간 도입 예정

728x90
반응형

+ Recent posts