메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

자바 8 람다 표현식과 스트림 유닛 테스트하기

한빛미디어

|

2015-01-28

|

by 한빛

21,837

제공 : 한빛 네트워크
저자 : Richard Warburton
역자 : 한승균
원문 : Unit Testing Java 8 Lambda Expressions and Streams


Lambda지난 18개월 정도 되는 시간 동안, 자바 8에서의 람다 표현식에 대해 많은 사람들에게 이야기했다. 당신이 Java 8에 대해 책을 쓰고 교육 과정까지 진행하고 있는 사람이라면, 이러는게 아주 이상한 일은 아닐 것이다! 내가 사람들에게 자주 받는 질문 중의 하나는, 람다 표현식이 테스트용 코드에 어떻게 영향을 미치는가? 이다. 점차 많은 사람들이 자신들의 프로젝트에서 자동화된 유닛 혹은 회귀 테스트 스위트를 사용하고 있고, 또 어떤 사람들은 테스트 주도 개발 방법론을 사용하고 있는 이런 시점에, 이 질문은 아주 적절하다고 본다. 이제부터 람다와 스트림을 사용하는 코드를 테스트할 때 마주칠 수 있는 문제들을 살펴보고, 어떻게 해결하는지 알아보자.

보통, 유닛 테스트 코드를 작성할 때는 애플리케이션에서 사용되는 메서드를 호출하는 식이다. 특정한 일이 벌어지도록 특정한 입력값을 제공하거나 이중으로 테스트하도록 메서드를 호출하고, 그러한 일이 벌어졌을 때 결과가 어떻게 바뀌어야 하는지 기술한다.

람다 표현식은 유닛 테스트 코드를 작성할 때 약간 다른 방식을 취한다. 왜냐하면 람다 표현식들은 이름이 없어서, 테스트용 코드에서 직접 호출할 수 없기 때문이다. 람다 표현식 코드를 테스트용 코드로 복사해서 그것을 테스트해볼 수도 있지만, 이런 방법은 실제 당신의 구현 결과를 테스트하는 것은 아니라는 부작용이 있다. 만약 당신이 구현한 부분의 코드를 바꾼다면, 실제 구현은 전혀 다른 일을 수행하지만, 테스트는 여전히 통과할 것이다.

이 문제를 해결할 수 있는 방법이 두 가지가 있다. 첫 번째 방법은 람다 표현식을 그것을 감싸고 있는 메서드 안의 코드 블럭의 관점으로 보는 것이다. 이 방법을 사용하면, 실제로는 람다 표현식 자체를 테스트한다기보다 감싸고 있는 메서드를 테스트하는 것이 된다.

아래와 같이 문자열의 리스트들을 대문자로 바꿔주는 예제 메소드를 예로 들어보자:

 

public static List<String> allToUpperCase(List<String> words) {

    return words.stream()

                .map(string -> string.toUpperCase())

                .collect(Collectors.toList());

}

 

이 코드에서 람다 표현식이 수행하는 것은 자바 메서드를 호출하는 것 뿐이다. 매우 간단한 일만 수행하기 때문에, 이 람다 표현식을 독립된 코드로 테스트까지 할 필요는 없어보인다.내가 이 코드를 유닛 테스트해야 한다면, 나는 메서드에 집중할 것이다. 예를 들어, 아래와 같이 스트림에 복수개의 단어가 있을 때, 이것들이 대문자로 잘 바뀌는지 테스트한다.

 

@Test

public void multipleWordsToUppercase() {

    List<String> input = Arrays.asList("a", "b", "hello");

    List<String> result = allToUpperCase(input);

    assertEquals(asList("A", "B", "HELLO"), result);

}

 

가끔 복잡한 기능에 람다 표현식을 사용하고 싶을 때도 있다. 이런 경우, 미처 발견하지 못한 문제들이 있을 수도 있고, 혹은 아주 중요한 역할을 수행하는 경우일 수도 있다. 이런 경우 반드시 테스트를 해볼 필요가 있는데, 람다 표현식으로 표현되어 있으니 이를 참조할 방법이 없는 것이다.

 

문자열의 리스트를 대문자로 바꾸는 것보다 좀 더 복잡한 메서드를 살펴보자. 이 메서드는 모든 문자열을 대문자로 바꾸는 것이 아니라, 첫 번째 글자만 바꾸고 나머지는 그대로 놔둘 것이다. 이것을 스트림과 람다 표현식으로 구현한다면, 아래와 같은 식이 될 것이다.

 

public static List<String> uppercaseFirstChar(List<String> words) {

    return words.stream()

                .map(value -> {

                    char firstChar = value.charAt(0);

    firstChar = toUpperCase(firstChar);

                    return firstChar + value.substring(1);

                })

                .collect(Collectors.toList());

}

이것을 테스트하기 위해서는 리스트를 사용해야 하고, 결과도 하나씩 모두 확인해야 한다. 아래의 예제는 이 방법이 얼마나 번거로워질 수 있는지 보여준다. 하지막 걱정하지 마라 - 해결책은 있다!

 

@Test

public void twoLetterStringConvertedToUppercaseLambdas() {

    List<String> input = Arrays.asList("ab");

    List<String> result = uppercaseFirstChar(input);

    assertEquals(Arrays.asList("Ab"), result);

}

 

람다 표현식을 사용하지 말아라! 람다 표현식에 대한 글에서 이상해 보일 수 있는 충고겠지만, 네모난 말뚝은 둥근 구멍에 잘 맞지 않는 법이다. 이것을 받아들인다면, 우리는 어떻게 우리의 코드를 테스트할 수 있으며, 또한 람다가 사용된 라이브러리의 이점을 활용할 수 있는지 살펴봐야 할 것이다.
메서드 레퍼런스를 이용하라. 람다 표현식으로 구현된 메서드는 보통의 메서드로도 구현될 수 있으며, 메서드 레퍼런스를 이용해 코드의 다른 곳에서 직접 참조할 수 있다. 아래의 코드에서, 람다 표현식을 별도의 메서드로 구현했다. 이 메서드는 메인 메서드에서 사용되고, 메인 메서드에서는 문자열의 리스트를 변환하는 것을 담당한다.

 

public static List<String> uppercaseFirstChar(List<String> words) {

    return words.stream()

                .map(Testing::firstToUppercase)

                .collect(Collectors.toList());

}

 

public static String firstToUppercase(String value) {

    char firstChar = value.charAt(0);

    firstChar = toUpperCase(firstChar);

    return firstChar + value.substring(1);

}

 

실제로 문자열을 처리하는 부분을 따로 메서드로 분리함으로써, 이 메서드를 테스트하면서 다양한 잠재적인 문제들을 해결할 수 있게 되었다. 위에서 했던 것과 같은 테스트는 아래에 더 간단한 모습으로 구현되었다.

 

@Test

public void twoLetterStringConvertedToUppercase() {

    String input = "ab";

    String result = uppercaseFirstChar(input);

    assertEquals("Ab", result);

}

 

이 글에서, 우리는 람다 표현식을 사용한 코드를 테스트하는 두가지 방법에 대해서 알아보았다. 하나는 람다 표현식을 그것을 감싸고 있는 메서드의 코드 블럭처럼 다루는 것이었다. 이런 접근은 람다 표현식이 테스트하기에 너무 간단한 경우에 적합하다 - getter 혹은 setter가 테스트하기에는 너무 간단한 경우와 비슷한 상황이다. 이런 종류의 람다 표현식들은 테스트할 필요가 없으므로 문제될 것이 없다. 또 다른 방법은, 더 복잡한 람다 표현식을 유닛 테스트하고 싶을 때 사용가능하다. 이 경우, 람다 표현식을 보통의 메서드로 추출해 내야 한다. 그리고 메서드 레퍼런스를 이용해 1등급 함수처럼 사용하면 된다. 이제 당신은 당신의 코드에서 람다를 안전하게 사용할 수 있는 준비를 갖추었다.
TAG :
댓글 입력
자료실

최근 본 상품0