728x90
반응형
제어할 수 없는 코드가 포함된 로직을 메소드 변경 없이 테스트 코드를 작성하는 방법(오버라이딩)
제어할 수 없는 코드가 포함된 레거시 코드를 받은 당신 🫵
당신은 아래의 레거시 코드를 받았고, move
라는 코드의 테스트 코드를 작성해야한다.
이때 당신은 어떻게 해야할 것인가?
public class Car {
public static final int FORWARD_NUMBER = 1;
private int position;
public void move() {
if (getRandom() >= FORWARD_NUMBER) {
position++;
}
}
private int getRandom() {
return Randoms.pickNumberInRange(0, 9);
}
public int getPosition() {
return position;
}
}
getRandom()
을 보니 내가 직접 제어할 수 없는 부분이다.
따라서 테스트 코드를 작성하면 경우에 따라서 성공할 수도 실패할 수도 있다.
class CarTest {
@Test
@DisplayName("1칸 이동")
void forward() {
// given
Car car = new Car();
// when
car.move();
// then
assertThat(car.getPosition()).isEqualTo(1);
}
@Test
@DisplayName("정지")
void stop() {
// given
Car car = new Car();
// when
car.move();
// then
assertThat(car.getPosition()).isEqualTo(0);
}
}
내가 제어 할 수 없으니까, move
메소드에 파라미터를 받도록 변경하자! 🥰
public class Car {
public static final int FORWARD_NUMBER = 1;
private int position;
public void move(int randomNumber) {
if (randomNumber >= FORWARD_NUMBER) {
position++;
}
}
private int getRandom() {
return Randoms.pickNumberInRange(0, 9);
}
public int getPosition() {
return position;
}
}
이렇게 변경하면, 우리는 randomNumber
를 통해 손쉽게 테스트 할 수 있다.
(제어할 수 없는 부분을 우리가 제어할 수 있게 변경했다.)
class CarTest {
@Test
@DisplayName("1칸 이동")
void forward() {
// given
Car car = new Car();
// when
car.move(1);
// then
assertThat(car.getPosition()).isEqualTo(1);
}
@Test
@DisplayName("정지")
void stop() {
// given
Car car = new Car();
// when
car.move(0);
// then
assertThat(car.getPosition()).isEqualTo(0);
}
}
오버라이딩
그런데, move
를 변경하려고 했을 때 move
가 사용되는 클래스가 1,000개가 넘는 상황이여서
메소드를 변경하게 되면 어떤 영향이 생길지 예측할 수 없다고 가정해보자…(😰 무서워…)
move
메소드를 변경하지 않고, move
를 테스트 할 수 있는 코드를 작성하려면 어떻게 해야할까…? 🤔
생각보다 간단하다. 😊
getRandom()
메소드의 접근권한을 private
에서 protected
로 변경하면 된다.!
public class Car {
public static final int FORWARD_NUMBER = 1;
private int position;
public void move() {
if (getRandom() >= FORWARD_NUMBER) {
position++;
}
}
public void move(int randomNumber) {
if (randomNumber >= FORWARD_NUMBER) {
position++;
}
}
// private를 protected로 변경한다!
protected int getRandom() {
return Randoms.pickNumberInRange(0, 9);
}
public int getPosition() {
return position;
}
}
왜 변경..하는거지….?
변경하면 뭐가 달라지는 거야..?🤷🏻♂️
바로 테스트 코드를 작성할 때, 오버라딩(재정의) 할 수 있기 때문이다!!!
class CarTest {
@Test
@DisplayName("1칸 이동")
void forward() {
// given
Car car = new Car() {
@Override
protected int getRandom() {
return 1;
}
};
// when
car.move();
// then
assertThat(car.getPosition()).isEqualTo(1);
}
@Test
@DisplayName("정지")
void stop() {
// given
Car car = new Car() {
@Override
protected int getRandom() {
return 0;
}
};
// when
car.move();
// then
assertThat(car.getPosition()).isEqualTo(0);
}
}
정말로 대박인거 같다. 👍
결론
- 레거시 코드에 내가 제어할 수 없는 코드가 포함되어 있는 로직이 있을 때, 테스트 코드를 작성하기 위해서 오버라이딩을 생각해보면 좋다!
참고
728x90
반응형
'0 + 프로그래밍 > 0 + Java' 카테고리의 다른 글
[10분 테코톡] 나는 제너릭을 모르고 개발했다. (0) | 2023.04.19 |
---|---|
[10분 테코톡] 나는 GC를 모르고 개발했다. (0) | 2023.03.07 |
[10분 테코톡] 나는 JVM를 모르고 개발했다. (0) | 2023.03.03 |