테스트와 OCP의 관계
테스트를 작성하는 여러 이유 중 하나는 객체 지향 설계 원칙 중 OCP(Open-Closed Principle)와 관련이 있다. 이 원칙은 클래스는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다는 것을 의미한다. 이 원칙을 지키지 않을 경우, 테스트하기 어려운 코드가 발생할 수 있다. 예를 들어, 랜덤한 숫자를 가져와야 하는 로직이 있다면, 이 로직을 테스트하는 것이 어려울 수 있다.
랜덤넘버를 이용한 코드와 테스트
[문제 상황]
랜덤한 숫자를 이용해서 게임을 진행하는 코드가 있다고 가정하자. 이러한 로직은 직접 테스트하기 어렵다.
public class RandomGame {
public String play() {
int randomNumber = (int) (Math.random() * 10);
if(randomNumber > 5) {
return "Win!";
} else {
return "Lose!";
}
}
}
위의 코드는 랜덤한 숫자에 따라 결과가 달라지기 때문에 예측 가능한 테스트를 작성하기 어렵다.
OCP를 적용한 해결 방안
OCP를 이용해서 문제를 해결하려면 랜덤 로직을 외부에서 주입받을 수 있도록 변경해야 한다. 이렇게 하면 테스트할 때는 랜덤 대신 예측 가능한 값을 사용할 수 있다.
[테스트하기 편한 예측 가능한 클래스]
public class RandomGame {
private final RandomNumberProvider randomNumberProvider;
public RandomGame(RandomNumberProvider randomNumberProvider) {
this.randomNumberProvider = randomNumberProvider;
}
public String play() {
int randomNumber = randomNumberProvider.getRandomNumber();
if(randomNumber > 5) {
return "Win!";
} else {
return "Lose!";
}
}
}
interface RandomNumberProvider {
int getRandomNumber();
}
[테스트 코드를 위한 구현] - 일반적으로는 테스트를 위해 클래스를 작성하면 안된다! (익명클래스 참고)
public class TestRandomNumberProvider implements RandomNumberProvider {
private final int number;
public TestRandomNumberProvider(int number) {
this.number = number;
}
@Override
public int getRandomNumber() {
return number;
}
}
[테스트 코드]
public class RandomGameTest {
@Test
public void givenNumberGreaterThan5_whenPlay_thenWin() {
RandomGame game = new RandomGame(new TestRandomNumberProvider(6));
assertThat(game.play()).isEqualTo("Win!");
}
@Test
public void givenNumberLessThan5_whenPlay_thenLose() {
RandomGame game = new RandomGame(new TestRandomNumberProvider(4));
assertThat(game.play()).isEqualTo("Lose!");
}
}
이와 같이 OCP를 적용하면 랜덤 로직을 Mocking하거나 대체 구현을 통해 예측 가능한 값을 사용하여 테스트할 수 있다. 이렇게 단위 테스트를 통해 빠른 피드백을 받고, 해당 클래스의 실패원자성을 보장할 수 있다.
'Study > 우아한 테크 코스' 카테고리의 다른 글
[우아한 테크 코스] 프리코스 - 4주차, 크리스마스 회고 (1) | 2023.11.21 |
---|---|
[우아한 테크 코스] 프리코스 - 3주차, 로또 회고 (0) | 2023.11.10 |
[우아한 테크 코스] 프리코스 - 2주차, 레이싱카 회고 (1) | 2023.11.04 |
private 메소드 테스트 꼭 해야 할까? (0) | 2023.11.02 |