Java: System.exit () yöntemini çağıran yöntemler nasıl sınanır?


199

System.exit()Bazı girişleri çağıracak birkaç yöntemim var . Ne yazık ki, bu vakaları test etmek JUnit'in sona ermesine neden oluyor! Yöntem çağrılarını yeni bir iş parçacığına koymak, System.exit()sadece geçerli iş parçacığı değil JVM'yi sonlandırdığından yardımcı görünmüyor . Bununla başa çıkmak için ortak kalıplar var mı? Örneğin, bir saplamayı değiştirebilir System.exit()miyim?

[EDIT] Söz konusu sınıf aslında JUnit içinde test etmeye çalıştığım bir komut satırı aracı. Belki de JUnit iş için doğru araç değildir? Tamamlayıcı regresyon test araçları için öneriler bekliyoruz (tercihen JUnit ve EclEmma ile iyi bütünleşen bir şey).


2
Neden bir işlevin neden System.exit () adını çağıracağını merak ediyorum
Thomas Owens

2
Uygulamadan çıkan bir işlevi çağırıyorsanız. Örneğin, kullanıcı üst üste x defadan fazla gerçekleştirme yetkisi olmayan bir görevi gerçekleştirmeye çalışırsa, bunları uygulamadan çıkarmaya zorlarsınız.
Elie

5
Hala bu durumda, System.exit () yerine uygulamadan dönmek için daha güzel bir yol olması gerektiğini düşünüyorum.
Thomas Owens

28
Main () öğesini test ediyorsanız, System.exit () öğesini çağırmak mükemmel olur. Hata halinde bir toplu işlemin 1 ile çıkması ve başarı ile 0 ile çıkması gerekir.
Matthew Farwell

5
System.exit()Kötü diyen herkese katılmıyorum - programınız hızlı bir şekilde başarısız olmalı. Bir istisna atmak, bir geliştiricinin çıkmak istediği ve sahte hatalar vereceği durumlarda uygulamayı yalnızca geçersiz bir durumda uzatır.
Sridhar Sarnobat

Yanıtlar:


218

Gerçekten, Derkeiler.com şunları önerir:

  • Neden System.exit()?

System.exit (whateverValue) ile sonlandırmak yerine, neden denetlenmeyen bir istisna atmıyorsunuz? Normal kullanımda, JVM'nin son hendek yakalayıcısına kadar sürüklenecek ve senaryonuzu kapatacaktır (yol boyunca bir yere yakalamaya karar vermediğiniz sürece, bir gün yararlı olabilir).

JUnit senaryosunda, JUnit çerçevesi tarafından yakalanacak ve bu tür testlerin başarısız olduğunu ve bir sonrakine sorunsuz bir şekilde geçeceğini bildirecektir.

  • JVM'den System.exit()gerçekten çıkmayı önleyin :

TestCase'i, System.exit çağrısını engelleyen bir güvenlik yöneticisiyle çalışacak şekilde değiştirmeyi deneyin ve ardından SecurityException'ı yakalayın.

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);
        }
    }
}

Aralık 2012 Güncellemesi:

Will önermektedir yorumlarda kullanarak Sistem Kuralları (4.9+) kurallar hangi kullandığı kod test etmek için, JUnit bir koleksiyon java.lang.System.
Bu başlangıçta tarafından sözü edilen Stefan Birkner içinde onun cevabını Aralık 2011'de.

System.exit(…)

Çağrıldığını ExpectedSystemExitdoğrulamak için kuralı kullanın System.exit(…).
Çıkış durumunu da doğrulayabilirsiniz.

Örneğin:

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
İlk yanıtı beğenmedim, ama ikincisi oldukça havalı - güvenlik yöneticileriyle uğraşmadım ve bundan daha karmaşık olduklarını varsaydım. Ancak, güvenlik yöneticisini / test mekanizmasını nasıl test edersiniz.
Bill K

8
Yırtma işleminin düzgün bir şekilde yürütüldüğünden emin olun, aksi takdirde JUnit uygulaması çıkamayacağı için testiniz Eclipse gibi bir koşucuda başarısız olur! :)
MetroidFan2002

6
Güvenlik yöneticisini kullanan çözümü sevmiyorum. Sadece sınamak için bana bir kesmek gibi görünüyor.
Nicolai Reuschling

7
Junit 4.7 veya daha yeni bir sürüm kullanıyorsanız, kütüphane System.exit çağrılarınızı yakalamakla ilgilensin. Sistem Kuralları - stefanbirkner.github.com/system-rules
Will

6
"System.exit (whateverValue) ile sonlandırmak yerine, neden denetlenmeyen bir istisna atmıyorsunuz?" - çünkü System.exitgeçersiz bir komut satırı argümanı sağlandığında çağıran komut satırı bağımsız değişken işleme çerçevesi kullanıyorum .
Adam Parkin

108

System Lambda kütüphanesinin bir yöntemi catchSystemExitvardır.Bu kurala göre System.exit (...) çağıran kodu test edebilirsiniz:

public void MyTest {
    @Test
    public void systemExitWithArbitraryStatusCode() {
        SystemLambda.catchSystemExit(() -> {
            //the code under test, which calls System.exit(...);
        });
    }
}

Java 5 - 7 için kütüphane Sistem Kuralları ExpectedSystemExit adında bir JUnit kuralına sahiptir. Bu kuralla, System.exit (...) öğesini çağıran kodu test edebilirsiniz:

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);
    }
}

Tam açıklama: Her iki kütüphanenin de yazarıyım.


3
Mükemmel. Zarif. Orijinal kodumun bir dikişini değiştirmek veya güvenlik yöneticisi ile oynamak zorunda kalmadım. Bu en iyi cevap olmalı!
Will

2
Bu en iyi cevap olmalı. System.exit öğesinin doğru kullanımı hakkında sürekli tartışma yerine, doğrudan konuya değin. Buna ek olarak, JUnit'in kendisine bağlı esnek bir çözüm, bu yüzden tekerleği yeniden icat etmemize veya güvenlik yöneticisiyle uğraşmamıza gerek yok.
L. Holanda

@LeoHolanda Bu çözüm, cevabımdaki düşüşü haklı çıkarmak için kullandığınız aynı "sorundan" muzdarip değil mi? Ayrıca, TestNG kullanıcıları ne olacak?
Rogério

2
@LeoHolanda Haklısın; kuralın uygulanmasına baktığımda, "sistem çıkışı" denetimi çağrısı gerçekleştiğinde özel bir güvenlik yöneticisi kullandığını ve bu nedenle testi sonlandırdığını görüyorum. Cevabımdaki eklenen örnek testi her iki gereksinimi de (System.exit çağrıldığında / çağrılmadan doğru doğrulama), BTW'yi karşılar. Kullanımı ExpectedSystemRuleelbette güzel; sorun, gerçek dünya kullanışlılığı açısından çok az şey sağlayan ve JUnit'e özgü ekstra bir üçüncü taraf kütüphanesi gerektirmesidir.
Rogério

2
Var exit.checkAssertionAfterwards().
Stefan Birkner

31

Bu Yöntemlere bir "ExitManager" enjekte etmeye ne dersiniz:

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
    }
}

Üretim kodu ExitManagerImpl kullanır ve test kodu ExitManagerMock kullanır ve exit () öğesinin çağrılıp çağrılmadığını ve hangi çıkış koduyla kontrol edilebilir.


1
+1 Güzel çözüm. ExitManager basit bir Bileşen haline geldiğinden Spring kullanıyorsanız da uygulanması kolaydır. ExitManager.exit () çağrısından sonra kodunuzun yürütülmeye devam etmediğinden emin olmanız gerektiğini unutmayın. Kodunuz bir sahte ExitManager ile test edildiğinde, exitManager.exit çağrısından sonra kod gerçekten çıkmaz.
Joman68

31

Aslında ,System.exit bir JUnit testinde yöntemi alay edebilir veya saplayabilirsiniz .

Örneğin, JMockit kullanarak yazabilirsiniz (başka yollar da vardır):

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


DÜZENLEME: Herhangi bir kodun çağrıldıktan sonra çalışmasına izin vermeyen alternatif sınama (en son JMockit API'sini kullanarak) 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
Aşağıya oylama nedeni: Bu çözümle ilgili sorun, System.exit koddaki son satır değilse (yani koşul içinde ise), kodun çalışmaya devam etmesidir.
L. Holanda

@LeoHolanda Aramadan sonra kodun çalışmasını engelleyen testin bir sürümü eklendi exit(gerçekten bir sorun değil, IMO).
Rogério

Son System.out.println () öğesini bir assert deyimi ile değiştirmek daha uygun olabilir mi?
user515655

"@Mocked (" exit ")", JMockit 1.43 ile artık çalışmıyor gibi görünüyor: "Alay edilen ek açıklama türü için öznitelik değeri tanımlanmamış" Dokümanlar: "Sahte alanları bildirirken kullanabileceğimiz üç farklı alaycı ek açıklama var ve parameters: @Mocked, alaycı bir sınıfın tüm mevcut ve gelecekteki örneklerinde tüm yöntemleri ve yapıcıları alay edecektir (bunu kullanan testlerin süresi boyunca); " jmockit.github.io/tutorial/Mocking.html#mocked
Thorsten Schöning

Aslında önerinizi denediniz mi? Ben olsun: "java.lang.IllegalArgumentException: Sınıf java.lang.System mockable değil" Runtimealay edilebilir, ama System.exiten azından Gradle Testler çalışan senaryomda durmaz.
Thorsten Schöning

20

Kod tabanımızda kullandığımız bir numara, System.exit () çağrısının, varsayılan olarak söz konusu yöntemin kullandığı bir Runnable impl'sinde kapsüllenmesini sağlamaktı. Birim testi yapmak için farklı bir sahte Runnable ayarladık. Bunun gibi bir şey:

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(); 
}

... ve JUnit test yöntemi ...

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

Buna bağımlılık enjeksiyonu mi diyorlar?
Thomas Ahle

2
Yazılan bu örnek bir tür yarı pişmiş bağımlılık enjeksiyonudur - bağımlılık, paket görünür foo yöntemine (genel foo yöntemi veya birim testi ile) geçirilir, ancak ana sınıf yine de varsayılan Runnable uygulamasını zor kodlar.
Scott Bale

6

System.exit () işlevini saran sahte bir sınıf oluşturma

EricSchaefer ile aynı fikirdeyim . Ancak Mockito gibi iyi bir alaycı çerçeve kullanırsanız , basit bir beton sınıfı yeterlidir, bir arayüze ve iki uygulamaya gerek yoktur.

System.exit () üzerinde test yürütülmesini durdurma

Sorun:

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

Bir alay konusu Sytem.exit()yürütmeyi sonlandırmaz. Yürütülmemiş olanı test etmek istiyorsanız bu kötüdür thing2.

Çözüm:

Martin tarafından önerilen bu kodu yeniden düzenlemelisiniz :

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

Ve System.exit(status)arama işlevinde yapın. Bu, tüm dosyalarınızı System.exit()içinde veya yakınında tek bir yerde bulundurmaya zorlar main(). Bu, System.exit()mantığınızın derinliklerine çağırmaktan daha temiz .

kod

sarıcı:

public class SystemExit {

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

Ana:

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;
    }
}

Ölçek:

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

Zaten verilen cevapların bazılarını seviyorum ama eski kod test edilirken genellikle yararlı farklı bir teknik göstermek istedim. Aşağıdaki gibi kod verildi:

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

System.exit çağrısını saran bir yöntem oluşturmak için güvenli bir yeniden düzenleme yapabilirsiniz:

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

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

Ardından, testiniz için çıkışı geçersiz kılan bir sahte oluşturabilirsiniz:

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;
    }
}

Bu, test senaryoları için davranış yerine kullanılan genel bir tekniktir ve eski kodu yeniden düzenlerken her zaman kullanıyorum. Genellikle bir şey bırakacağım yer değil, mevcut kodu test altına almak için bir ara adım.


2
Bu teknikler, exit () çağrıldığında kontrol akışını durdurmaz. Bunun yerine bir İstisna kullanın.
Andrea Francia

3

Api'ye hızlı bir bakış, System.exit öğesinin bir istisna esp'si atabileceğini gösterir. eğer bir güvenlik yöneticisi vm'nin kapatılmasını yasaklarsa. Belki böyle bir yöneticiyi kurmak bir çözüm olabilir.


3

Geçerli iş parçacığının Java VM'sini kapatmasını önlemek için java SecurityManager'ı kullanabilirsiniz. Aşağıdaki kod istediğinizi yapmalıdır:

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);

Hm. System.exit belgeleri özellikle name = "exitVM" ile checkPermission değil, checkExit (int) öğesinin çağrılacağını belirtir. Her ikisini de geçersiz kılmalı mıyım acaba?
Chris Conway

İzin adı aslında exitVM (durum kodu), yani exitVM.0 gibi görünüyor - en azından son OSX testimde.
Mark Derricutt

3

VonC'nin cevabının JUnit 4'te çalışması için kodu aşağıdaki gibi değiştirdim

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 (..) öğesini Runtime örneğini değiştirerek test edebilirsiniz. TestNG + Mockito ile:

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

Dönen çıkış kodunun çağıran program tarafından kullanıldığı ortamlar vardır (MS Batch içindeki ERRORLEVEL gibi). Kodumuzda bunu yapan ana yöntemler etrafında testlerimiz var ve yaklaşımımız, burada diğer testlerde kullanılana benzer bir SecurityManager geçersiz kılma kullanmaktı.

Dün gece, güvenlik yöneticisi kodunu gizlemek için Junit @ Kural ek açıklamalarını kullanarak küçük bir JAR hazırladım ve beklenen dönüş koduna göre beklentiler ekledim. http://code.google.com/p/junitsystemrules/


2

Çoğu çözüm

  • Anı System.exit()çağrıldığında testi (yöntem, tüm çalışma değil) sonlandırın
  • önceden kurulmuş olanları yoksay SecurityManager
  • Bazen bir test çerçevesine oldukça spesifik olun
  • test senaryosu başına maksimum bir kez kullanılmasını kısıtla

Bu nedenle, çoğu çözüm aşağıdaki durumlarda uygun değildir:

  • Yan etkilerin doğrulanması, şu çağrıdan sonra yapılacaktır: System.exit()
  • Mevcut bir güvenlik yöneticisi testin bir parçasıdır.
  • Farklı bir test çerçevesi kullanılır.
  • Tek bir test durumunda birden çok doğrulama yapmak istiyorsunuz. Bu kesinlikle tavsiye edilmeyebilir, ancak özellikle assertAll()örneğin ile birlikte zaman zaman çok uygun olabilir .

Diğer cevaplarda sunulan mevcut çözümlerin getirdiği kısıtlamalardan memnun değildim ve bu yüzden kendi başıma bir şey buldum.

Aşağıdaki sınıf bir yöntem temin assertExits(int expectedStatus, Executable executable)belirtmektedir System.exit()belirli bir çağrılır statusdeğeri ve test bunu sonra da devam edebilir. JUnit 5 ile aynı şekilde çalışır assertThrows. Ayrıca mevcut bir güvenlik yöneticisine de saygı gösterir.

Kalan bir sorun var: Test edilen kod, test tarafından ayarlanan güvenlik yöneticisinin yerini alan yeni bir güvenlik yöneticisi yüklediğinde. SecurityManagerBenim bildiğim diğer tüm tabanlı çözümler aynı problemle karşı karşıya.

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;
        }
    }
}

Sınıfı şu şekilde kullanabilirsiniz:

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

Kod, gerekirse JUnit 4, TestNG veya başka bir çerçeveye kolayca taşınabilir. Çerçeveye özgü tek öğe testin başarısız olmasıdır. Bu kolayca çerçeve bağımsız bir şeye değiştirilebilir ( 4 Haziran dışında) Rule

assertExits()Özelleştirilebilir mesajlarla aşırı yükleme gibi iyileştirme için yer vardır .


1

Runtime.exec(String command)JVM'yi ayrı bir işlemde başlatmak için kullanın .


3
Ünite testinden ayrı bir süreçteyse, test edilen sınıfla nasıl etkileşim kuracaksınız?
DNA

1
Vakaların% 99'unda System.exit ana yöntemin içindedir. Bu nedenle, onlarla komut satırı bağımsız değişkenleri (örn. Argümanlar) ile etkileşime girersiniz.
L. Holanda

1

Çözümde küçük bir sorun var SecurityManager. Gibi bazı yöntemler JFrame.exitOnClosede çağırır SecurityManager.checkExit. Başvurumda, bu çağrının başarısız olmasını istemedim, bu yüzden kullandım

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

0

Bir main () içinde yapılmadıkça System.exit () öğesini çağırmak kötü bir uygulamadır. Bu yöntemler, sonuçta main () tarafından yakalanan ve daha sonra System.exit öğesini uygun kodla çağıran bir istisna atmalıdır.


8
Yine de bu soruya cevap vermiyor. Test edilen işlev eninde sonunda ana yöntem ise? Bu nedenle, System.exit () yönteminin çağrılması geçerli ve tasarım açısından iyi olabilir. Bunun için nasıl bir test senaryosu yazıyorsunuz?
Elie

3
Ana yöntem sadece herhangi bir argüman almalı, bunları bir ayrıştırıcı yöntemine geçirmeli ve daha sonra uygulamayı başlatmalıdır. Test edilecek ana yöntemde mantık olmamalıdır.
Thomas Owens

5
@Elie: Bu tür sorularda iki geçerli cevap vardır. Biri soruyu cevapladı ve biri sorunun nedenini sordu. Her iki cevap türü daha iyi bir anlayış ve özellikle her ikisini birlikte verir.
runaros
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.