public void drive() {
Random random = new Random();
int number = random.nextInt(10);
if (number >= 4) {
position += 1;
}
}
자동차는 랜덤한 숫자를 하나 선택하고, 이가 4 이상이면 전진한다.
자동차의 전진 여부를 테스트하기 위해선 어떻게 해야할까?
@DisplayName("자동차 전진 테스트")
@Test
void driveTest() {
Car car = new Car("test");
car.drive();
assertThat(car.getPosition()).isEqualTo(1);
}
이렇게 테스트하면.. 0~3이면 실패고, 4~9면 성공이니 60% 확률로 성공한다.
그러면 이를 @RepeatedTest(1000) 걸고 600번정도 성공하면 성공적으로 전진한것일까?
그렇게 불확실한 테스트를 과연 테스트라 부를 수 있을까?
그러면 이 친구를 테스트하기 위해선 어떻게 해야할까?
전략 패턴을 사용해 테스트하자
우선, NumberGenerator 인터페이스를 생성하고, 이를 상속받는 RandomNumberGenerator를 구현한다.
// NumberGenerator.java
public interface NumberGenerator {
int generate();
}
// RandomNumberGenerator.java
public class RandomNumberGenerator implements NumberGenerator {
private static final Random random = new Random();
@Override
public int generate() {
return random.nextInt(10);
}
}
다음으로 자동차 객채 생성시 RandomNumberGenerator를 주입해주고, 전진여부 판단 숫자를 고를 때 NumberGenerator를 사용한다.
// Car 객체 생성시 RandomNumberGenerator 주입
new Car("test", new RandomNumberGenerator());
// Car.java
public class Car {
public Car(final String name, NumberGenerator numberGenerator) {
this.name = name;
this.numberGenerator = numberGenerator;
}
public void drive() {
final int DRIVING_DISTANCE = 1;
final int MOVING_STANDARD = 4;
int number = numberGenerator.generate();
if (number >= 4) {
drivenDistance += 1;
}
}
}
이제 테스트를 위한 DrivableNumberGenerator과 NonDrivableNumberGenerator를 만들어주자!
이는 테스트를 위한 클래스들로, test 패키지 내에 위치시키자.
class DrivableNumberGenerator implements NumberGenerator {
@Override
public int generate() {
return 4;
}
}
class NonDrivableNumberGenerator implements NumberGenerator {
@Override
public int generate() {
return 3;
}
}
위 두 클래스를 이용해 테스트를 해주자!
@DisplayName("차량 전진 테스트")
@Test
void driveTest() {
//given
Car car = new Car("test", new DrivableNumberGenerator());
//when
car.drive();
//then
assertThat(car.getPosition()).isEqualTo(1);
}
@DisplayName("차량 정지 테스트")
@Test
void nonDriveTest() {
//given
Car car = new Car("test", new NonDrivableNumberGenerator());
//when
car.drive();
//then
assertThat(car.getPosition()).isEqualTo(0);
}
'우테코 5기 > 레벨1' 카테고리의 다른 글
[체스 미션] 상속 대신 전략패턴 도입하기 (4) | 2023.03.28 |
---|---|
정적 팩토리 메서드로 생성자 다이어트 시키기 (4) | 2023.03.05 |
View단에서 도메인 객체를 생성해 return하는게 좋을까, 아니면 입력값을 그대로 return하는게 좋을까? (3) | 2023.02.17 |
입력값 검증을 InputView에서 진행할까, Domain에서 진행할까? (1) | 2023.02.17 |
상수를 하나의 클래스에 모으는 것이 좋을까? (0) | 2023.02.17 |