-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
웹 백엔드 미션 유틸리티 라이브러리를 제작한다. - 7월 28일 #87
Comments
테스트케이스가 여러개인경우, Scanner가 닫히는 상황을 해결한다.Sol 1
public class WoowaScanner {
private static Scanner scanner;
public static void run() {
// 다른 테스트 때마다 App이 다시도니, App 최초 실행시 run 메소드를 호출하여 System.in을 다시 받으면 해결
scanner = new Scanner(System.in);
}
public static String nextLine() {
return scanner.nextLine();
}
public static Integer nextInt() {
return scanner.nextInt();
}
} package utils;
import java.io.IOException;
public class App {
public static void main(String[] args) throws IOException {
// 지우지 말라는 코멘트
WoowaScanner.run();
// =======아래부터 코드를 작성하도록 유도========= //
App app = new App();
app.run();
}
} @DisplayName("입력과 숫자를 입력받고, 출력한다.")
@ParameterizedTest
@CsvSource({"시드,-1", "포츈,1"})
void 이름과_숫자를_입력(final String name, final String number) {
assertSimpleTest(() -> {
subject(
name, number,
// 종료 트리거
STOP
);
assertThat(captor.toString().trim()).contains(name, number);
});
}
Wrong Casepublic class WoowaScanner {
// 필드에서 생성, 관리할시 여러 입력에 대한 처리는 되나, 다른 테스트에서 문제발생.
// @CsvSource({"시드", "포츈"})
private static Scanner scanner = new Scanner(System.in);
public static String nextLine() {
// @CsvSource({"시드,포츈"})
// 내부에서 생성시 다른테스트에 대한 처리는 되나, 여러 입력에 대한 처리가 안됨.
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
}
그외 시도해본방법
|
Wrong CaseInputView에서 Scanner를 스태틱으로 생성하고, 생성한 스캐너를 이용해서 사용자 입력을 받는 메소드를 만들었다. 그 후 테스트 코드에서 getInput() 메소드를 모킹하여 원하는 결과를 출력하도록 하려고 했다. public class InputView {
private static final Scanner SCANNER = new Scanner(System.in);
public static String getInput() {
return SCANNER.nextLine();
}
}
@ParameterizedTest
@ValueSource(strings = {"시드", "포츈"})
void 잘못된_상품_구매_이름_테스트(final String productName) {
try (MockedStatic<InputView> inputViewMock = Mockito.mockStatic(InputView.class)) {
inputViewMock.when(InputView::getInput).thenReturn("2", productName, MAIN_EXIT_NUMBER);
assertSimpleTest(() -> {
...
} 하지만 모킹한 메소드가 아닌, 실제 메소드인 SCANNER.nextLine()가 실행되었고, 프로그램은 사용자의 입력을 기다렸다가 일정 시간동안 입력이 들어오지 않아 실패했다. MockedStatic은 현재 스레드를 키로, 설정한 목 메소드를 밸류로 갖는다. assertSimpleTest는 [junit-timeout-thread-1, 5, main]라는 새로운 스레드를 생성 후, 그 스레드에서 테스트를 실행한다. 그래서 기존 [main, 5, main]과 매핑되어 있던 목 메소드가 아닌, [junit-timeout-thread-1, 5, main]과 매핑된 메소드를 실행한다. 매핑된 메소드가 새로운 스레드를 생성하는 것이 아닌 기존 스레드에서 타임아웃을 체크해야 한다. 코드가 복잡해져서 이 방법은 포기하기로 했다. |
Sol 2리플렉션을 사용해 Scanner가 닫혔는지 확인하고 닫혔다면 새로 생성하도록 했습니다. public class ScannerUtils {
private static Scanner scanner = getScanner();
public static String nextLine() {
makeNewScannerIfScannerIsClosed();
return scanner.nextLine();
}
public static int nextInt() {
makeNewScannerIfScannerIsClosed();
return scanner.nextInt();
}
// 스캐너가 닫혀있다면 새로운 스캐너 생성
private static void makeNewScannerIfScannerIsClosed() {
if (scanner == null || scannerIsClosed()) {
scanner = getScanner();
}
}
// Scanner의 private 필드 sourceClosed를 리턴
private static boolean scannerIsClosed() {
try {
Field sourceClosedField = Scanner.class.getDeclaredField("sourceClosed");
sourceClosedField.setAccessible(true);
return sourceClosedField.getBoolean(scanner);
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println("리플렉션 중 에러 발생");
}
return true;
}
private static Scanner getScanner() {
return new Scanner(System.in);
}
} |
피드백 반영
중앙 저장소 다운로드.allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.Joyykim:wooteco-utils:0.0.3'
} |
No description provided.
The text was updated successfully, but these errors were encountered: