본문 바로가기
Java

Enum 타입 에 따른 테스트(DynamicTest)

by ybs 2023. 2. 18.
반응형

커머스 관련 개발을 하다보니 수많은 Enum 들을 만나게 된다. 아래 Enum 은 간단한 상품타입 코드다. 단순 옵션과 복잡한 옵션 두개의 타입이 있다. 

public enum ProductType {
	SIMPLE_OPTION,
	COMPLEX_OPTION
}

 

상품타입에 따라 달라지는 부분을 테스트 하기 위해선 ParameterizedTest 와 EnumSource 를 사용하면 된다. 

@ParameterizedTest
@EnumSource(names = {"SIMPLE_OPTION", "COMPLEX_OPTION"})
void enumSourceTest(ProductType productType) {
	System.out.println(productType);
}

 

하지만 Enum 들 관계에 따라 비지니스 로직이 분기처리되는 경우는 매우 흔하고 그부분을 테스트하고 싶다. 아래 코드는 상품레벨의 상품타입과 그 하위인 아이템레벨의 아이템타입 관계를 표현했다. ProdcutType 과 ItemType 조합의 모든 경우의 수는 8가지지만, 실질적으로 가능한 조합은 4가지다.

@Value
@Builder
public class Product {
	ProductType productType;

	List<Item> items;

	@Value
	@Builder
	public static class Item {
		ItemType itemType;
	}
}

// ProductType 과 ItemType 의 관계
// SIMPLE_OPTION - SIMPLE
// COMPLEX_OPTION - COMBINATION1
// COMPLEX_OPTION - COMBINATION2
// COMPLEX_OPTION - COMBINATION3
public enum ProductType {
	SIMPLE_OPTION,
	COMPLEX_OPTION
}

public enum ItemType {
	SIMPLE,
	COMBINATION1,
	COMBINATION2,
	COMBINATION3,
}

 

그래서 위 4가지 조합을 따로 셋팅해줘야 하는데 ParameterizedTest 와 MethodSource 를 활용할 수 있다.

@ParameterizedTest
@MethodSource("productTypeAndItemTypeSet")
void methodSourceTest(ProductType productType, ItemType itemType) {
	System.out.println(productType + " : " + itemType);
}

private static Stream productTypeAndItemTypeSet() {
	return Stream.of(
		Arguments.of(
			ProductType.SIMPLE_OPTION,
			ItemType.SIMPLE
		),
		Arguments.of(
			ProductType.COMPLEX_OPTION,
			ItemType.COMBINATION1
		),
		Arguments.of(
			ProductType.COMPLEX_OPTION,
			ItemType.COMBINATION2
		),
		Arguments.of(
			ProductType.COMPLEX_OPTION,
			ItemType.COMBINATION3
		)
	);
}

 

org.junit.jupiter.api.DynamicTest 와 TestFactory 를 활용하는 방법도 있다. 코드를 먼저 보자. Stream.of 로 4가지 Enum 조합을 셋팅해주고 flatMap 에서 각각 DynamicTest.dynamicTest 를 돌리는 구조다.

@TestFactory // @Test 가 아니라 @TestFactory 다
Stream<DynamicTest> dynamicTestTest() {
	return Stream.of(
			Map.of(ProductType.SIMPLE_OPTION, ItemType.SIMPLE),
			Map.of(ProductType.COMPLEX_OPTION, ItemType.COMBINATION1),
			Map.of(ProductType.COMPLEX_OPTION, ItemType.COMBINATION2),
			Map.of(ProductType.COMPLEX_OPTION, ItemType.COMBINATION3)
		)
		.flatMap(testCaseMap ->
			testCaseMap.entrySet().stream()
				.map(it ->
					DynamicTest.dynamicTest(testCaseMap.toString(), () -> {
						ProductType productType = it.getKey();
						ItemType itemType = it.getValue();

						System.out.println(productType + " : " + itemType);
						}
					)
				)
		);
	}
}

 

자바는 기본적으로 Pair 클래스를 제공하지 않아서 Map 을 썼더니 flatMap 을 써야하는 등 코드가 좀 복잡하게 구현됐다.

코틀린 버전으로 그리고 Pair 를 써서 만들면 더 심플하긴 하다.

@TestFactory
fun dynamicTestTest(): Stream<DynamicTest> {
    return Stream.of(
        Pair(ProductType.SIMPLE_OPTION, ItemType.SIMPLE),
        Pair(ProductType.COMPLEX_OPTION, ItemType.COMBINATION1),
        Pair(ProductType.COMPLEX_OPTION, ItemType.COMBINATION2),
        Pair(ProductType.COMPLEX_OPTION, ItemType.COMBINATION3),
    )
        .map { pair ->
            DynamicTest.dynamicTest(pair.toString()) {
                println("${pair.first} : ${pair.second}")
            }
        }
}

 

cf) 자바에서 기본적으로 제공은 안하지만 스프링에서 제공해주는 org.springframework.data.util.Pair 를 사용할 수 있다.

반응형