inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

Practical Testing: 실용적인 테스트 가이드

테스트 환경의 독립성을 보장하자

테스트 given절 작성 시, "팩토리 메서드를 통한 생성 지양" 관련 문의

228

ykm8864

작성한 질문수 4

0

 강의에서 테스트 given절에서 팩토리 메서드를 통한 객체 생성은 어떠한 의도가 들어갈 수 있으므로 지양하라고 하셨습니다. 관련하여 질문이 있습니다.

 

예를 들어 다음과 같은 팩토리 메서드가 있다고 하면,

public class Coffee {

private String type;

private int size;

public Coffee(String type, int size) {

this.type = type;

this.size = size;

}

}

public class SeasonalCoffeeFactory {

public static Coffee createCoffee(String season) {

switch (season.toLowerCase()) {

case "summer":

return new Coffee("Iced Coffee", 50);

case "winter":

return new Coffee("Hot Coffee", 30);

case "spring":

return new Coffee("Latte", 40);

case "fall":

return new Coffee("Pumpkin Spice Latte", 45);

default:

throw new IllegalArgumentException("Unknown season: " + season);

}

}

}



여름 시즌 커피에 대한 테스트 코드는 다음과 같을 겁니다.

@Test

public void testCreateSummerCoffee() {

Coffee coffee = SeasonalCoffeeFactory.createCoffee("summer");

assertEquals("Iced Coffee", coffee.getType());

assertEquals(50, coffee.getSize());

}



이때 테스트 코드는 시즌에 맞는 커피 메뉴를 given절에 생성한 후 타입 일치여부만 판단하면 됩니다.

하지만 이 부분을 팩토리 메서드로 작성하지 않게되면
커피를 생성함에 있어
if ("summer".equalsIgnoreCase(season)) {

coffee = new Coffee("Iced Coffee", 50);

} else if...

와 같은 부분이 테스트 코드의 given절에 들어가야하지 않나 싶습니다. 물론 이런 부분에 대해서 if라는 논리구조가 들어갔으니 한번 더 테스트 코드 메서드가 분리되어야하는건가 싶기도 한데 확신이 잘 안 서서 질문 드리고 싶습니다.

긴 글 읽어주셔서 감사합니다.

spring tdd jpa mockito 소프트웨어-테스트 junit5 팩토리메서드

답변 2

0

박우빈

안녕하세요, ykm8864 님!

먼저 질문 드리고 싶은 것은, 현재 테스트하려는 대상(when절)이 무엇인가요?

  • SeasonalCoffeeFactory.createCoffee() 가 테스트 대상이라면,

    • Coffee coffee = SeasonalCoffeeFactory.createCoffee("summer"); 로 여름 시즌에 대한 커피가 잘 생성되었는지를 검증하시면 됩니다.

  • 검증하려는 대상이 Factory.createCoffee()가 아니라 Coffee의 다른 메서드이거나, 혹은 Coffee를 사용하는 다른 객체라면,

    • Coffee라는 fixture를 생성할 때 특정 상황에 맞는 Coffee를 다이렉트로 생성하라는 의미입니다.

    • Factory를 통해 생성한 Coffee는, 만약 Factory의 내부 로직이 변경되었을 경우 전혀 상관 없는 이 곳 메서드까지 영향을 줄 수 있거든요.

정리하면, 검증 대상인 when절에서 팩토리 메서드를 사용하지 말라는 것이 아니라, given절의 fixture를 만들 때 그러지 않기를 이야기하는 것입니다.

도움이 되셨기를 바랍니다.
감사합니다. 🙂

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. ykm8864님!

질문해주신 ‘팩토리 메서드를 통한 객체 생성 지양’이라는 원칙에 대해 설명드리겠습니다. 강의에서는 새로운 인스턴스를 생성할 때 팩토리 메서드 대신 생성자나 빌더 패턴을 사용하는 것을 권장했죠. 이는 팩토리 메서드가 추가적인 의도를 내포하게 되어 테스트의 독립성과 순수성을 저해할 수 있기 때문입니다.

여름 시즌 커피 예시로 들면, 팩토리 메서드를 사용하면 커피 타입과 크기가 시즌별로 결정되는 로직이 감춰집니다. 이를 테스트할 때는, 단순히 팩토리 메서드를 호출한 결과만 확인하는 것이 아니라, 이러한 로직이 기대대로 작동하는지도 검증해야 합니다.

테스트 코드를 작성할 때 if문 같은 조건문을 걱정하시는 것 같습니다. 하지만 중요한 것은, 테스트되고 있는 기능이 무엇인지 명확히 하고, 그 기능에 대한 기대 결과를 확인하는 것입니다. 팩토리 메서드 내에서 선언된 로직이 복잡하다면 해당 로직에 대한 별도의 단위 테스트가 필요할 수 있습니다.

수강생님이 말씀하셨듯이, 조건부 로직이 길어질 경우 별도의 테스트 메서드나 테스트 클래스를 도입하여 이를 분리할 수 있습니다. 이는 테스트 코드의 가독성 및 유지보수성을 높이는 데 도움이 됩니다.

관련된 강의 게시물로는 팩토리메서드를 지양하고 생성자 혹은 Builder 패턴을 쓰라는 말씀에 관하여라는 질문 게시물이 있습니다. 여기에서 팩토리 메서드의 사용과 관련해 생성자나 빌더 패턴을 사용하는 이유에 대해 자세히 다루고 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

private 상수 테스트 관련 질문

0

87

1

void는 어떻게 테스트하나요..? void로 애초에 코딩하면 안되나요??

0

128

2

커버리지는 어떻게 활용하시는지 궁금합니다.

0

163

2

테스트 문서화 질문입니다

0

107

2

단위테스트 질문이 있습니다

0

96

2

컨트롤러는 모킹을 한 이유가 궁금합니다.

0

106

2

ERD 가장자리에 있는 도메인 테스트 질문

0

90

2

DTO 검증 필드에 대한 테스트 코드 작성은 어디까지?

0

136

2

OrderCreateRequest DTO에 대해서 궁금한점

0

104

2

고전파의 테스트 대역 사용 대상, 공유 의존성

0

157

2

계층 관련 질문이 있습니다.

0

140

3

'코틀린'에서는 빌더를 따로 쓰지 않는데, 이 때는 어떻게 test fixture를 만드시는지 궁금합니다

1

124

2

혹시 update 로직은 어떻게 테스트하나요? (@Setter?)

0

135

2

단위테스트와 통합테스트의 경계가 궁금합니다.

0

235

2

Service+Repository 통합테스트 관련 질문입니다.

0

151

2

OrderControllerDocsTest 작성 해봤는데요. 날짜 형식이 이상하게 나와요

0

186

2

test 용 .yml

0

91

2

throws Exception

0

81

2

카페키오스크 클래스 문의 ,,

0

90

2

Rest docs 문서용 테스트코드를 따로 작성해야 되나요?

0

176

2

테스트 코드에서 필요한 생성자

0

139

1

tearDown 순서

0

116

2

@Builder 생성자 private

0

137

2

@DisplayName gradle / intellJ

0

94

2