인프런 커뮤니티 질문&답변

hxcva1님의 프로필 이미지
hxcva1

작성한 질문수

Readable Code: 읽기 좋은 코드를 작성하는 사고법

Value Object

입출력 테스트 관련 질문 있습니다!

작성

·

74

·

수정됨

0

  • 학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!

  • 먼저 유사한 질문이 있었는지 검색해 보세요.

  • 서로 예의를 지키며 존중하는 문화를 만들어가요.

     

 안녕하세요. 우선 강의로 너무 많은 도움을 받았습니다! 감사합니다.

 

다름이 아니라 로드맵을 따라 해당 강의와 테스트 코드 작성 강의를 모두 수강했는데 현재 지뢰찾기와 스터디카페에서는 콘솔에서 입출력을 받게 되는데 입출력에 대한 예외처리를 InputHandler가 하는 것처럼 다가왔습니다.

이부분에서 테스트를 작성하려고 하는데 입출력에 대한 테스트를 작성하기 어려워서 과연 InputHander가 입력에 대한 검증 책임까지 가지고 있는가에 대해서 궁금하고 만약 분리해야 한다면 어떻게 분리하는 것이 좋을 지도 궁금합니다.

 

또한 현재의 경우 콘솔로 입출력을 받아 테스트가 어렵게 다가오는데 이런 경우

이때 만약 전체 서비스가 외부에서 유저의 입력을 문자열을 받는 형태로 분리해야하는데 이 경우에 외부에서도 입출력을 하고, 내부에서도 입출력을 하게 되어 어떻게 하면 좋을지 고민이 되고

혹은 현재 그대로 콘솔로 테스트 하는 것이 좋을지 궁금합니다. 콘솔에서 입출력을 받을 때 테스트 코드를 작성하는 방법도 알 수 있을까요??

 

그리고 테스트 강의의 테스트 환경의 독립성을 보장하자 강의에서 테스트 코드에서는 객체를 생성할 때 생성자로 생성해서 테스트해야한다고 말씀을 하셨는데 만약 특정 필드가 기본값을 가져야 해서 생성자를 private로 막은 후 정적 팩토리 메서드를 이용해 생성된다면 이러한 경우 기본값을 가지는 특정 필드를 어떻게 특정 값으로 세팅해서 테스트 할 수 있을지도 궁금합니다.

이런 경우 생성자, getter 같은 테스트만을 위한 코드를 넣어도 된다고 하셨는데 이런 경우 원하는 객체의 불변성이 깨지는 것 같아서 어떻게 하면 좋을지 궁금합니다.

 

 

감사합니다

답변 2

0

박우빈님의 프로필 이미지
박우빈
지식공유자

안녕하세요, hxcva1 님!

 

이부분에서 테스트를 작성하려고 하는데 입출력에 대한 테스트를 작성하기 어려워서 과연 InputHander가 입력에 대한 검증 책임까지 가지고 있는가에 대해서 궁금하고 만약 분리해야 한다면 어떻게 분리하는 것이 좋을 지도 궁금합니다.

InputHandler가 입력에 대한 검증 책임을 반드시 가져야하는지, 정해진 것은 없습니다. 도메인을 이해하고, 설계하는 방향에 따라 달라질 수 있는 내용이에요.
현재의 요구사항에서는 InputHandler가 가져야 하는 책임이 이 정도면 충분하겠다고 생각할 수도 있고, 이후 도메인 요구사항이 변경됨에 따라 책임을 나누거나 변경하시면 됩니다.

 

또한 현재의 경우 콘솔로 입출력을 받아 테스트가 어렵게 다가오는데 이런 경우

이때 만약 전체 서비스가 외부에서 유저의 입력을 문자열을 받는 형태로 분리해야하는데 이 경우에 외부에서도 입출력을 하고, 내부에서도 입출력을 하게 되어 어떻게 하면 좋을지 고민이 되고

혹은 현재 그대로 콘솔로 테스트 하는 것이 좋을지 궁금합니다. 콘솔에서 입출력을 받을 때 테스트 코드를 작성하는 방법도 알 수 있을까요??

질문하신 내용을 잘 이해하지는 못했는데요, 일단 예제 도메인 기준으로 콘솔 입출력에 대한 테스팅은 핵심 도메인보다 테스트 중요도가 떨어집니다.
만약 출력되는 문자열이 중요하다면, 문자열을 생성하거나 제공하는 부분만 출력 부분에서 따로 분리하여 테스트를 진행할 수도 있겠습니다.
입출력 테스트는 여러 방법이 있을 수 있겠지만, InputStream, OutputStream을 직접 정의하여 입력되거나 출력되는 데이터를 임의의 값으로 지정할 수 있습니다.

그리고 테스트 강의의 테스트 환경의 독립성을 보장하자 강의에서 테스트 코드에서는 객체를 생성할 때 생성자로 생성해서 테스트해야한다고 말씀을 하셨는데 만약 특정 필드가 기본값을 가져야 해서 생성자를 private로 막은 후 정적 팩토리 메서드를 이용해 생성된다면 이러한 경우 기본값을 가지는 특정 필드를 어떻게 특정 값으로 세팅해서 테스트 할 수 있을지도 궁금합니다.

기본값을 가져야 해서 생성자를 private으로 막고, 정적 팩토리 메서드만 열려있다면, 정적 팩토리 메서드를 테스트하면서 기본값이 잘 생성되었는지를 검증하면 될 것 같아요.
만약 해당 값이 변화된 상태의 fixture를 생성하고 싶은거라면, 테스트에서만 Builder를 사용하거나, Reflection을 사용해서 특정 값을 주입해줄 수 있을 것 같아요.

감사합니다. 🙂

0

안녕하세요, 인프런 AI 인턴입니다.
hxcva1님께서 남기신 질문에 대해 답변 드리겠습니다.

입출력 테스트와 관련된 고민이 많으신 것 같습니다. 콘솔에서 입출력을 테스트하는 방법에 대해서는 OutputCapture라는 JUnit Extension을 활용하여 System.outSystem.err 출력을 캡처할 수 있습니다. 이 방법을 사용하면 콘솔로부터의 출력을 테스트할 수 있습니다. 사용 방법은 다음과 같습니다.

Java 코드 예제:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {

    @Test
    void testName(CapturedOutput output) {
        System.out.println("Hello World!");
        assertThat(output).contains("World");
    }
}

Kotlin 코드 예제:

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension

@ExtendWith(OutputCaptureExtension::class)
class MyOutputCaptureTests {

    @Test
    fun testName(output: CapturedOutput?) {
        println("Hello World!")
        assertThat(output).contains("World")
    }
}

이러한 방식으로 콘솔 출력을 캡처하고 테스트할 수 있습니다.

추가적으로, 생성자의 접근 제어자와 정적 팩토리 메서드의 사용에 대한 질문도 주셨습니다. 기본값을 가지는 특정 필드를 테스트하는 경우, 테스트 코드에서는 목적에 맞게 설계 방침을 약간 수정해도 괜찮습니다. 하지만, 테스트를 위해 임시로 생성자나 getter를 추가해야만 한다면, 이는 불변성을 고려한 후에 결정해야 하는 부분입니다. 테스트 지원을 위한 학습적인 설계일 수 있으며, 실제 프로덕션 코드에서는 그 접근을 조심할 필요가 있습니다.

아무쪼록 고민하시는 부분에 도움이 되었길 바랍니다. 추가적인 질문이 있으시면 언제든지 말씀해주세요!

OutputCapture 관련 문서

hxcva1님의 프로필 이미지
hxcva1

작성한 질문수

질문하기