Java : System.exit ()를 호출하는 메소드를 테스트하는 방법?


198

System.exit()특정 입력을 호출 해야하는 몇 가지 방법이 있습니다. 불행히도, 이러한 경우를 테스트하면 JUnit이 종료됩니다! 메소드 호출을 새 스레드에 넣는 것은 System.exit()현재 스레드뿐만 아니라 JVM을 종료하기 때문에 도움이되지 않는 것 같습니다 . 이 문제를 처리하는 데 일반적인 패턴이 있습니까? 예를 들어, 스텁을 대체 할 수 System.exit()있습니까?

[편집] 문제의 클래스는 실제로 JUnit 내에서 테스트하려는 명령 행 도구입니다. 아마도 JUnit이 그 일에 적합한 도구가 아닐 수도 있습니다. 보완 회귀 테스트 도구에 대한 제안을 환영합니다 (JUnit 및 EclEmma와 잘 통합 된 것).


2
함수가 왜 System.exit ()를 호출하는지 궁금합니다.
Thomas Owens

2
응용 프로그램을 종료하는 함수를 호출하는 경우 예를 들어, 사용자가 작업을 수행하려고하면 x 번 이상 연속으로 수행 할 권한이 없으면 응용 프로그램에서 강제로 종료합니다.
Elie

5
이 경우에도 System.exit () 대신 응용 프로그램에서 반환하는 더 좋은 방법이 있어야한다고 생각합니다.
토마스 오웬스

27
main ()을 테스트하는 경우 System.exit ()를 호출하는 것이 좋습니다. 오류가 발생하면 배치 프로세스가 1로 종료되고 성공하면 0으로 종료해야한다는 요구 사항이 있습니다.
Matthew Farwell

5
나는 System.exit()나쁜 말을하는 모든 사람들에 동의하지 않습니다-당신의 프로그램은 빨리 실패해야합니다. 예외를 throw하면 개발자가 종료하려고하고 잘못된 오류가 발생하는 상황에서 응용 프로그램이 유효하지 않은 상태로 유지됩니다.
Sridhar Sarnobat

답변:


216

실제로 Derkeiler.com 은 다음 과 같이 제안합니다.

  • System.exit()?

System.exit (whateverValue)로 종료하는 대신 확인되지 않은 예외를 발생시키지 않는 이유는 무엇입니까? 정상적인 사용에서는 JVM의 마지막 도랑 포수로 표류하고 스크립트를 종료합니다 (어딘가에 어딘가에 스크립트를 잡기로 결정하지 않는 한 언젠가는 유용 할 수 있습니다).

JUnit 시나리오에서는 JUnit 프레임 워크에 의해 포착됩니다. JUnit 프레임 워크는 이러한 테스트가 실패했음을보고하고 다음 단계로 원활하게 이동합니다.

  • 방지는 System.exit()실제로 JVM을 종료합니다 :

System.exit 호출을 방해하는 보안 관리자로 실행되도록 TestCase를 수정 한 다음 SecurityException을 포착하십시오.

public class NoExitTestCase extends TestCase 
{

    protected static class ExitException extends SecurityException 
    {
        public final int status;
        public ExitException(int status) 
        {
            super("There is no escape!");
            this.status = status;
        }
    }

    private static class NoExitSecurityManager extends SecurityManager 
    {
        @Override
        public void checkPermission(Permission perm) 
        {
            // allow anything.
        }
        @Override
        public void checkPermission(Permission perm, Object context) 
        {
            // allow anything.
        }
        @Override
        public void checkExit(int status) 
        {
            super.checkExit(status);
            throw new ExitException(status);
        }
    }

    @Override
    protected void setUp() throws Exception 
    {
        super.setUp();
        System.setSecurityManager(new NoExitSecurityManager());
    }

    @Override
    protected void tearDown() throws Exception 
    {
        System.setSecurityManager(null); // or save and restore original
        super.tearDown();
    }

    public void testNoExit() throws Exception 
    {
        System.out.println("Printing works");
    }

    public void testExit() throws Exception 
    {
        try 
        {
            System.exit(42);
        } catch (ExitException e) 
        {
            assertEquals("Exit status", 42, e.status);
        }
    }
}

2012 년 12 월 업데이트 :

제안 코멘트에 사용하는 시스템 규칙 (4.9+) 규정 된 사용하는 코드를 테스트하기 위해, JUnit을의 컬렉션을 java.lang.System.
이것은 처음에 언급 한 스테판 버크 너그의 대답 2011 년 12 월.

System.exit(…)

ExpectedSystemExit규칙을 사용하여 System.exit(…)호출 되었는지 확인 하십시오 .
종료 상태도 확인할 수 있습니다.

예를 들어 :

public void MyTest {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void noSystemExit() {
        //passes
    }

    @Test
    public void systemExitWithArbitraryStatusCode() {
        exit.expectSystemExit();
        System.exit(0);
    }

    @Test
    public void systemExitWithSelectedStatusCode0() {
        exit.expectSystemExitWithStatus(0);
        System.exit(0);
    }
}

4
첫 번째 대답은 마음에 들지 않았지만 두 번째 대답은 멋지다. 나는 보안 관리자를 엉망으로 만들지 않았고 그보다 더 복잡하다고 생각했다. 그러나 보안 관리자 / 테스트 메커니즘을 어떻게 테스트합니까?
Bill K

6
해체가 올바르게 실행되는지 확인하십시오. 그렇지 않으면 JUnit 애플리케이션을 종료 할 수 없으므로 Eclipse와 같은 러너에서 테스트가 실패합니다! :)
MetroidFan2002

6
보안 관리자를 사용하는 솔루션이 마음에 들지 않습니다. 그것을 테스트하기 위해 나에게 해킹처럼 보인다.
Nicolai Reuschling 12

6
junit 4.7 이상을 사용하는 경우 라이브러리가 System.exit 호출 캡처를 처리하도록하십시오. 시스템 규칙 - stefanbirkner.github.com/system-rules

6
"System.exit (whateverValue)로 종료하는 대신 검사되지 않은 예외를 발생시키지 않는 이유는 무엇입니까?" System.exit잘못된 명령 줄 인수가 제공 될 때마다 호출하는 명령 줄 인수 처리 프레임 워크를 사용하고 있기 때문 입니다.
Adam Parkin

106

라이브러리 시스템 규칙 에는 ExpectedSystemExit라는 JUnit 규칙이 있습니다. 이 규칙을 사용하면 System.exit (...)를 호출하는 코드를 테스트 할 수 있습니다.

public void MyTest {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void systemExitWithArbitraryStatusCode() {
        exit.expectSystemExit();
        //the code under test, which calls System.exit(...);
    }

    @Test
    public void systemExitWithSelectedStatusCode0() {
        exit.expectSystemExitWithStatus(0);
        //the code under test, which calls System.exit(0);
    }
}

전체 공개 : 저는 그 도서관의 저자입니다.


3
완전한. 우아한. 원래 코드의 스티치를 변경하거나 보안 관리자와 함께 놀 필요가 없었습니다. 이것이 최고의 답변이어야합니다!

2
이것이 최고의 답변이되어야합니다. System.exit의 올바른 사용에 대한 끊임없는 논쟁 대신, 그 요점을 직접 찾으십시오. 또한 JUnit 자체를 준수하는 유연한 솔루션이므로 보안 관리자와의 관계를 망칠 필요가 없습니다.
L. Holanda

@LeoHolanda이 솔루션이 내 대답에 대한 공감대를 정당화하는 데 사용한 것과 같은 "문제"로 고통받지 않습니까? 또한 TestNG 사용자는 어떻습니까?
Rogério

2
@LeoHolanda 당신이 맞아요; 규칙의 구현을 살펴보면 이제 "시스템 종료"점검 호출이 발생할 때 예외가 발생하여 테스트를 종료하는 사용자 정의 보안 관리자를 사용하는 것을 볼 수 있습니다. 내 대답에 추가 된 예제 테스트는 BTW의 두 가지 요구 사항 (System.exit이 호출되거나 호출되지 않는 적절한 확인)을 충족시킵니다. ExpectedSystemRule물론 사용 은 좋습니다. 문제는 실제 유용성 측면에서 거의 제공하지 않으며 JUnit 전용의 추가 타사 라이브러리가 필요하다는 것입니다.
Rogério

2
있습니다 exit.checkAssertionAfterwards().
스테판 버크 너

31

이 메소드에 "ExitManager"를 주입하는 방법은 다음과 같습니다.

public interface ExitManager {
    void exit(int exitCode);
}

public class ExitManagerImpl implements ExitManager {
    public void exit(int exitCode) {
        System.exit(exitCode);
    }
}

public class ExitManagerMock implements ExitManager {
    public bool exitWasCalled;
    public int exitCode;
    public void exit(int exitCode) {
        exitWasCalled = true;
        this.exitCode = exitCode;
    }
}

public class MethodsCallExit {
    public void CallsExit(ExitManager exitManager) {
        // whatever
        if (foo) {
            exitManager.exit(42);
        }
        // whatever
    }
}

프로덕션 코드는 ExitManagerImpl을 사용하고 테스트 코드는 ExitManagerMock을 사용하며 exit ()가 호출되었는지 여부와 종료 코드를 확인할 수 있습니다.


1
+1 좋은 해결책. ExitManager가 간단한 컴포넌트가되어 Spring을 사용한다면 쉽게 구현할 수 있습니다. exitManager.exit () 호출 후에 코드가 계속 실행되지 않도록해야합니다. 모의 ExitManager로 코드를 테스트하는 경우 exitManager.exit를 호출 한 후에 코드가 실제로 종료되지 않습니다.
Joman68

31

실제로 JUnit 테스트에서 메소드를 조롱하거나 스텁 아웃 할 수 있습니다System.exit .

예를 들어, JMockit 을 사용 하면 다음과 같이 작성할 수 있습니다 (다른 방법도 있음).

@Test
public void mockSystemExit(@Mocked("exit") System mockSystem)
{
    // Called by code under test:
    System.exit(); // will not exit the program
}


편집 : 호출 후 코드를 실행할 수없는 대체 테스트 (최신 JMockit API 사용) System.exit(n):

@Test(expected = EOFException.class)
public void checkingForSystemExitWhileNotAllowingCodeToContinueToRun() {
    new Expectations(System.class) {{ System.exit(anyInt); result = new EOFException(); }};

    // From the code under test:
    System.exit(1);
    System.out.println("This will never run (and not exit either)");
}

2
투표 이유 :이 솔루션의 문제점은 System.exit가 코드의 마지막 행이 아닌 경우 (예 : 내부 조건) 코드가 계속 실행된다는 것입니다.
L. Holanda

@LeoHolanda exit호출 후 코드가 실행되지 않도록하는 테스트 버전을 추가 했습니다 (실제로 문제가 된 것은 아닙니다).
Rogério

마지막 System.out.println ()을 assert 문으로 바꾸는 것이 더 적절할 수 있습니까?
user515655

"@Mocked ("exit ")"가 JMockit 1.43에서 더 이상 작동하지 않는 것 같습니다 : "주석 유형 Mocked에 대해 속성 값이 정의되지 않았습니다"문서 : "모의 필드를 선언 할 때 사용할 수있는 세 가지 다른 조롱 주석이 있습니다. 매개 변수 : @Mocked. 기존의 그리고 미래의 조롱 클래스의 모든 인스턴스에서 모든 메소드와 생성자를 조롱합니다 (사용하는 테스트 기간 동안). " jmockit.github.io/tutorial/Mocking.html#mocked
Thorsten Schöning

실제로 제안을 시도 했습니까? "java.lang.IllegalArgumentException : 클래스 java.lang.System은 Runtime조롱 할 수 없습니다" 를 조롱 할 수 있지만 System.exitGradle에서 Tests를 실행하는 시나리오에서는 적어도 멈추지 않습니다 .
Thorsten Schöning 님이

20

코드베이스에서 사용한 한 가지 트릭은 System.exit ()에 대한 호출을 Runnable impl에 캡슐화하는 것입니다. 문제의 메소드는 기본적으로 사용됩니다. 단위 테스트를 위해 다른 모의 Runnable을 설정했습니다. 이 같은:

private static final Runnable DEFAULT_ACTION = new Runnable(){
  public void run(){
    System.exit(0);
  }
};

public void foo(){ 
  this.foo(DEFAULT_ACTION);
}

/* package-visible only for unit testing */
void foo(Runnable action){   
  // ...some stuff...   
  action.run(); 
}

... 그리고 JUnit 테스트 방법 ...

public void testFoo(){   
  final AtomicBoolean actionWasCalled = new AtomicBoolean(false);   
  fooObject.foo(new Runnable(){
    public void run(){
      actionWasCalled.set(true);
    }   
  });   
  assertTrue(actionWasCalled.get()); 
}

이것이 의존성 주입이라고하는 것입니까?
Thomas Ahle

2
작성된이 예제는 일종의 반 베이크 종속성 주입입니다. 종속성은 공개 foo 메소드 또는 단위 테스트를 통해 패키지 표시 가능 foo 메소드로 전달되지만 기본 클래스는 여전히 기본 Runnable 구현을 하드 코딩합니다.
Scott Bale

6

System.exit ()를 감싸는 모의 가능한 클래스를 만듭니다.

EricSchaefer에 동의합니다 . 그러나 Mockito 와 같은 훌륭한 조롱 프레임 워크를 사용하면 간단한 구체적인 클래스로 충분하며 인터페이스와 두 가지 구현이 필요하지 않습니다.

System.exit ()에서 테스트 실행 중지

문제:

// do thing1
if(someCondition) {
    System.exit(1);
}
// do thing2
System.exit(0)

조롱 Sytem.exit()은 실행을 종료하지 않습니다. thing2실행되지 않은 테스트하려는 경우에는 좋지 않습니다.

해결책:

martin 이 제안한 대로이 코드를 리팩터링해야합니다 .

// do thing1
if(someCondition) {
    return 1;
}
// do thing2
return 0;

그리고 System.exit(status)호출 기능을 수행하십시오. 이것은 당신 System.exit()의 모든 것을 한곳 또는 그 근처에 두게 main()합니다. 이것은 System.exit()논리 내부를 깊이 파헤치는 것보다 깨끗 합니다.

암호

싸개:

public class SystemExit {

    public void exit(int status) {
        System.exit(status);
    }
}

본관:

public class Main {

    private final SystemExit systemExit;


    Main(SystemExit systemExit) {
        this.systemExit = systemExit;
    }


    public static void main(String[] args) {
        SystemExit aSystemExit = new SystemExit();
        Main main = new Main(aSystemExit);

        main.executeAndExit(args);
    }


    void executeAndExit(String[] args) {
        int status = execute(args);
        systemExit.exit(status);
    }


    private int execute(String[] args) {
        System.out.println("First argument:");
        if (args.length == 0) {
            return 1;
        }
        System.out.println(args[0]);
        return 0;
    }
}

테스트:

public class MainTest {

    private Main       main;

    private SystemExit systemExit;


    @Before
    public void setUp() {
        systemExit = mock(SystemExit.class);
        main = new Main(systemExit);
    }


    @Test
    public void executeCallsSystemExit() {
        String[] emptyArgs = {};

        // test
        main.executeAndExit(emptyArgs);

        verify(systemExit).exit(1);
    }
}

5

나는 이미 주어진 답변 중 일부를 좋아하지만 테스트중인 레거시 코드를 얻을 때 종종 유용한 다른 기술을 보여주고 싶었습니다. 주어진 코드 :

public class Foo {
  public void bar(int i) {
    if (i < 0) {
      System.exit(i);
    }
  }
}

안전한 리팩토링을 수행하여 System.exit 호출을 래핑하는 메소드를 작성할 수 있습니다.

public class Foo {
  public void bar(int i) {
    if (i < 0) {
      exit(i);
    }
  }

  void exit(int i) {
    System.exit(i);
  }
}

그런 다음 exit를 재정의하는 가짜 테스트를 만들 수 있습니다.

public class TestFoo extends TestCase {

  public void testShouldExitWithNegativeNumbers() {
    TestFoo foo = new TestFoo();
    foo.bar(-1);
    assertTrue(foo.exitCalled);
    assertEquals(-1, foo.exitValue);
  }

  private class TestFoo extends Foo {
    boolean exitCalled;
    int exitValue;
    void exit(int i) {
      exitCalled = true;
      exitValue = i;
    }
}

이것은 테스트 사례의 동작을 대체하는 일반적인 기술이며 레거시 코드를 리팩토링 할 때 항상 사용합니다. 일반적으로 내가 떠날 곳이 아니라 테스트중인 기존 코드를 얻는 중간 단계입니다.


2
이 기술은 exit ()가 호출 될 때 제어 흐름을 중지하지 않습니다. 대신 예외를 사용하십시오.
Andrea Francia

3

api를 간단히 살펴보면 System.exit가 예외 esp를 던질 수 있음을 보여줍니다. 보안 관리자가 vm 종료를 금지하는 경우 해결책은 그러한 관리자를 설치하는 것일 수 있습니다.


3

java SecurityManager를 사용하여 현재 스레드가 Java VM을 종료하지 못하게 할 수 있습니다. 다음 코드는 원하는 것을 수행해야합니다.

SecurityManager securityManager = new SecurityManager() {
    public void checkPermission(Permission permission) {
        if ("exitVM".equals(permission.getName())) {
            throw new SecurityException("System.exit attempted and blocked.");
        }
    }
};
System.setSecurityManager(securityManager);

흠. System.exit 문서는 특히 checkPermission (int)이 name = "exitVM"인 checkPermission이 아니라 호출 될 것이라고 말합니다. 둘 다 재정의해야하는지 궁금합니다.
Chris Conway

권한 이름은 실제로 exitVM. (statuscode), 즉 exitVM.0 인 것 같습니다. 최소한 최근 OSX 테스트에서.
Mark Derricutt

3

JUnit 4에서 VonC의 답변을 실행하려면 다음과 같이 코드를 수정했습니다.

protected static class ExitException extends SecurityException {
    private static final long serialVersionUID = -1982617086752946683L;
    public final int status;

    public ExitException(int status) {
        super("There is no escape!");
        this.status = status;
    }
}

private static class NoExitSecurityManager extends SecurityManager {
    @Override
    public void checkPermission(Permission perm) {
        // allow anything.
    }

    @Override
    public void checkPermission(Permission perm, Object context) {
        // allow anything.
    }

    @Override
    public void checkExit(int status) {
        super.checkExit(status);
        throw new ExitException(status);
    }
}

private SecurityManager securityManager;

@Before
public void setUp() {
    securityManager = System.getSecurityManager();
    System.setSecurityManager(new NoExitSecurityManager());
}

@After
public void tearDown() {
    System.setSecurityManager(securityManager);
}

3

런타임 인스턴스를 교체하여 System.exit (..)를 테스트 할 수 있습니다. 예 : TestNG + Mockito 사용 :

public class ConsoleTest {
    /** Original runtime. */
    private Runtime originalRuntime;

    /** Mocked runtime. */
    private Runtime spyRuntime;

    @BeforeMethod
    public void setUp() {
        originalRuntime = Runtime.getRuntime();
        spyRuntime = spy(originalRuntime);

        // Replace original runtime with a spy (via reflection).
        Utils.setField(Runtime.class, "currentRuntime", spyRuntime);
    }

    @AfterMethod
    public void tearDown() {
        // Recover original runtime.
        Utils.setField(Runtime.class, "currentRuntime", originalRuntime);
    }

    @Test
    public void testSystemExit() {
        // Or anything you want as an answer.
        doNothing().when(spyRuntime).exit(anyInt());

        System.exit(1);

        verify(spyRuntime).exit(1);
    }
}

2

리턴 된 종료 코드가 호출 프로그램에 의해 사용되는 환경이 있습니다 (예 : MS Batch의 ERRORLEVEL). 코드에서이 작업을 수행하는 주요 메소드에 대한 테스트가 있으며 다른 테스트에서 사용 된 것과 유사한 SecurityManager 재정의를 사용했습니다.

어젯밤 Junit @Rule 어노테이션을 사용하는 작은 JAR을 작성하여 보안 관리자 코드를 숨기고 예상 리턴 코드를 기반으로 기대치를 추가했습니다. http://code.google.com/p/junitsystemrules/


2

대부분의 솔루션은

  • 모멘트 System.exit()가 호출 되는 테스트 종료 (전체 실행이 아닌 메소드)
  • 이미 설치된 무시 SecurityManager
  • 때때로 테스트 프레임 워크에 매우 구체적
  • 테스트 사례 당 최대 한 번만 사용하도록 제한

따라서 대부분의 솔루션은 다음과 같은 상황에 적합하지 않습니다.

  • 부작용 확인은 전화를 한 후 수행해야합니다. System.exit()
  • 기존 보안 관리자가 테스트의 일부입니다.
  • 다른 테스트 프레임 워크가 사용됩니다.
  • 단일 테스트 사례에서 여러 번의 검증을 원합니다. 이것은 엄격하게 권장되지는 않지만 특히 예를 들어와 함께 사용 assertAll()하면 매우 편리 할 수 ​​있습니다 .

나는 다른 답변에 제시 된 기존 솔루션에 의해 부과 된 제한에 만족하지 않아서 스스로 무언가를 생각해 냈습니다.

다음 클래스는 지정된 값으로 호출 assertExits(int expectedStatus, Executable executable)되는 어설 션을 제공하며 테스트 후에도 계속할 수 있습니다. JUnit 5와 같은 방식으로 작동합니다 . 또한 기존 보안 관리자를 존중합니다.System.exit()statusassertThrows

테스트중인 코드가 테스트에 의해 설정된 보안 관리자를 완전히 대체하는 새 보안 관리자를 설치하는 경우 하나의 문제가 남아 있습니다. SecurityManager나에게 알려진 다른 모든 솔루션은 같은 문제를 겪습니다.

import java.security.Permission;

import static java.lang.System.getSecurityManager;
import static java.lang.System.setSecurityManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

public enum ExitAssertions {
    ;

    public static <E extends Throwable> void assertExits(final int expectedStatus, final ThrowingExecutable<E> executable) throws E {
        final SecurityManager originalSecurityManager = getSecurityManager();
        setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(final Permission perm) {
                if (originalSecurityManager != null)
                    originalSecurityManager.checkPermission(perm);
            }

            @Override
            public void checkPermission(final Permission perm, final Object context) {
                if (originalSecurityManager != null)
                    originalSecurityManager.checkPermission(perm, context);
            }

            @Override
            public void checkExit(final int status) {
                super.checkExit(status);
                throw new ExitException(status);
            }
        });
        try {
            executable.run();
            fail("Expected System.exit(" + expectedStatus + ") to be called, but it wasn't called.");
        } catch (final ExitException e) {
            assertEquals(expectedStatus, e.status, "Wrong System.exit() status.");
        } finally {
            setSecurityManager(originalSecurityManager);
        }
    }

    public interface ThrowingExecutable<E extends Throwable> {
        void run() throws E;
    }

    private static class ExitException extends SecurityException {
        final int status;

        private ExitException(final int status) {
            this.status = status;
        }
    }
}

다음과 같이 클래스를 사용할 수 있습니다.

    @Test
    void example() {
        assertExits(0, () -> System.exit(0)); // succeeds
        assertExits(1, () -> System.exit(1)); // succeeds
        assertExits(2, () -> System.exit(1)); // fails
    }

필요한 경우 코드를 JUnit 4, TestNG 또는 기타 프레임 워크로 쉽게 포팅 할 수 있습니다. 프레임 워크 고유의 유일한 요소는 테스트에 실패한 것입니다. 이것은 Junit 4 이외의 프레임 워크 독립적 인 것으로 쉽게 변경 될 수 있습니다. Rule

예를 들어, assertExits()사용자 정의 가능한 메시지로 오버로드 하는 개선의 여지가 있습니다 .


1

Runtime.exec(String command)별도의 프로세스에서 JVM을 시작하는 데 사용하십시오 .


3
단위 테스트와 별도의 프로세스 인 경우 테스트중인 클래스와 어떻게 상호 작용합니까?
DNA

1
99 %의 경우 System.exit가 기본 메소드 내에 있습니다. 따라서 명령 행 인수 (예 : args)로 상호 작용합니다.
L. Holanda

1

SecurityManager솔루션에 사소한 문제가 있습니다. 와 같은 일부 메소드 JFrame.exitOnClose도 호출 SecurityManager.checkExit합니다. 내 응용 프로그램에서 호출이 실패하지 않기를 원했기 때문에

Class[] stack = getClassContext();
if (stack[1] != JFrame.class && !okToExit) throw new ExitException();
super.checkExit(status);

0

System.exit () 호출은 main () 내부에서 수행되지 않는 한 나쁜 습관입니다. 이 메소드는 예외를 발생시켜 궁극적으로 main ()에 의해 잡히고 적절한 코드로 System.exit를 호출합니다.


8
그래도 질문에 대답하지 않습니다. 테스트중인 기능이 궁극적으로 주된 방법이라면? 따라서 디자인 관점에서 System.exit () 호출은 유효하고 괜찮을 수 있습니다. 테스트 케이스는 어떻게 작성합니까?
Elie

3
main 메소드는 인수를 가져 와서 파서 메소드에 전달한 다음 응용 프로그램을 시작하기 때문에 main 메소드를 테스트 할 필요는 없습니다. 테스트 할 기본 메소드에는 로직이 없어야합니다.
토마스 오웬스

5
@Elie : 이러한 유형의 질문에는 두 가지 유효한 답변이 있습니다. 하나는 질문에 대답하고 다른 하나는 질문의 근거가 된 이유를 묻습니다. 두 가지 유형의 답변 모두 더 나은 이해를 제공합니다.
runaros December
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.