본문 바로가기
공부/Java

테스트하기 좋은 메서드 만들기 (인터페이스 분리)

by JERO__ 2022. 3. 14.

테스트하기 어려운 메서드

public class Car {

    private static final int MOVABLE_LOWER_BOUND = 4;
    private static final int RANDOM_NUMBER_UPPER_BOUND = 10;

    private final String name;
    private int position;

    public Car(String name, int position) {
        this.name = name;
        this.position = position;
    }

    public void move() {
        final int number = random.nextInt(RANDOM_NUMBER_UPPER_BOUND);

        if (number >= MOVABLE_LOWER_BOUND) {
            position++;
        }
    }
}

- 자동차 경주 게임 미션 예시

 

1. 해결방법 - 메서드 수정

- move 메서드에서 매개변수로 number 를 받고록 수정

public void move(int number) {
    if (number >= MOVABLE_LOWER_BOUND) {
        position++;
    }
}

But ...

- 의존 관계를 상위로 이동시킨 것에 불과하다. 테스트 코드에 영향을 미치지 않는 곳까지 의존 관계를 이동시킨다면,

어디서 사용되는지(랜덤 한 값 생성객체)를 찾기 매우 어려울 수 있다.

 

2. 해결방법 - 전략 패턴을 사용한 인터페이스 분리

- 해결한 move 메서드는 number매개변수로 받는다.

- 즉, 인터페이스에는 int타입을 반환하는 메서드를 구현해야 한다.

 

1. 인터페이스 생성

public interface NumberGenerator {
    int generate();
}

2. 메서드에 적용

public void move(NumberGenerator numberGenerator) {
    final int number = numberGenerator.generate();

    if (number >= MOVABLE_LOWER_BOUND) {
        position++;
    }
}

3. 해당 인터페이스를 상속받은 클래스 구현

public class RandomNumberGenerator implements NumberGenerator {
    private static final int RANDOM_NUMBER_UPPER_BOUND = 10;

    @Override
    public int generate() {
        return random.nextInt(RANDOM_NUMBER_UPPER_BOUND);
    }
}

 

적용한 뒤 테스트 코드 작성

- 테스트를 위한 구현(인터페이스 상속)

public class MovableNumberGenerator implements NumberGenerator {
    @Override
    public int generate() {
        return 4;
    }
}

- 테스트코드

public class CarTest {

    @DisplayName("숫자가 4보다 크거나 같으면 위치를 1 증가")
    @Test
    public void move_NumberIsEqualOrGreaterThanFour_IncreasePositionByOne() {
        final Car car = new Car("스티치", 1);
        final NumberGenerator numberGenerator = new MovableNumberGenerator();
        car.move(numberGenerator);
        
        assertThat(car).extracting("position").isEqualTo(2);
    }
}

 

최종정리

- 메서드 시그니처를 수정하는 방법보다 인터페이스 생성하는 방법이 응집도가 더 높다.

 

참고

https://tecoble.techcourse.co.kr/post/2020-05-17-appropriate_method_for_test_by_interface/

'공부 > Java' 카테고리의 다른 글

Stream.forEach와 Collection.forEach의 차이  (0) 2022.03.17
클래스와 인스턴스  (0) 2022.03.15
Optional<T>  (0) 2022.03.13
스트림(Stream) - 3 (스트림 연산)  (0) 2022.03.13
스트림(Stream) - 2 (스트림 만들기)  (0) 2022.03.13

댓글