Wie teste ich, dass keine Ausnahme ausgelöst wird?

238

Ich weiß, dass ein Weg, dies zu tun, wäre:

@Test
public void foo(){
   try{
      //execute code that you expect not to throw Exceptions.
   }
   catch(Exception e){
      fail("Should not have thrown any exception");
   }
}

Gibt es einen saubereren Weg, dies zu tun? (Vermutlich mit Junits @Rule?)

Ankit Dhingra
quelle
10
Ein JUnit-Test wird als fehlgeschlagen beurteilt, wenn er eine andere Ausnahme als eine erwartete Ausnahme auslöst. Normalerweise werden keine Ausnahmen erwartet.
Raedwald
Gibt es in JUnit nicht einen Unterschied zwischen Fehler und Irrtum? Das erste bedeutet, dass der Test fehlgeschlagen ist, das zweite bedeutet, dass etwas Unerwartetes passiert ist.
Vituel
1
mögliches Duplikat von Wie kann ich testen, ob eine bestimmte Ausnahme nicht ausgelöst wird?
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Antworten:

198

Sie nähern sich dem falsch. Testen Sie einfach Ihre Funktionalität: Wenn eine Ausnahme ausgelöst wird, schlägt der Test automatisch fehl. Wenn keine Ausnahme ausgelöst wird, werden Ihre Tests alle grün angezeigt.

Ich habe festgestellt, dass diese Frage von Zeit zu Zeit auf Interesse stößt, daher werde ich ein wenig darauf eingehen.

Hintergrund zu Unit-Tests

Wenn Sie Unit-Tests durchführen, ist es wichtig, selbst zu definieren, was Sie als Arbeitseinheit betrachten. Grundsätzlich gilt: eine Extraktion Ihrer Codebasis, die mehrere Methoden oder Klassen enthalten kann oder nicht, die eine einzelne Funktionalität darstellen.

Oder wie in The art of Unit Testing, 2. Auflage von Roy Osherove , Seite 11 definiert:

Ein Komponententest ist ein automatisierter Code, der die zu testende Arbeitseinheit aufruft und dann einige Annahmen über ein einzelnes Endergebnis dieser Einheit überprüft. Ein Unit-Test wird fast immer mit einem Unit-Test-Framework geschrieben. Es kann einfach geschrieben werden und läuft schnell. Es ist vertrauenswürdig, lesbar und wartbar. Die Ergebnisse sind konsistent, solange sich der Produktionscode nicht geändert hat.

Es ist wichtig zu erkennen, dass eine Arbeitseinheit normalerweise nicht nur eine Methode ist, sondern im Grunde genommen eine Methode, und danach wird sie von einer anderen Arbeitseinheit gekapselt.

Geben Sie hier die Bildbeschreibung ein

Idealerweise sollten Sie für jede einzelne Arbeitseinheit eine Testmethode haben, damit Sie immer sofort sehen können, wo etwas schief geht. In diesem Beispiel gibt es eine grundlegende Methode, getUserById()die einen Benutzer zurückgibt, und es gibt insgesamt 3 Arbeitseinheiten.

Die erste Arbeitseinheit sollte prüfen, ob bei gültigen und ungültigen Eingaben ein gültiger Benutzer zurückgegeben wird.
Alle Ausnahmen, die von der Datenquelle ausgelöst werden, müssen hier behandelt werden: Wenn kein Benutzer vorhanden ist, sollte ein Test durchgeführt werden, der zeigt, dass eine Ausnahme ausgelöst wird, wenn der Benutzer nicht gefunden werden kann. Ein Beispiel hierfür könnte das sein, das IllegalArgumentExceptionmit der @Test(expected = IllegalArgumentException.class)Anmerkung abgefangen wird .

Sobald Sie alle Ihre Anwendungsfälle für diese grundlegende Arbeitseinheit bearbeitet haben, steigen Sie eine Ebene höher. Hier machen Sie genau das Gleiche, aber Sie behandeln nur die Ausnahmen, die von der Ebene direkt unter der aktuellen kommen. Dies hält Ihren Testcode gut strukturiert und ermöglicht es Ihnen, schnell durch die Architektur zu laufen, um herauszufinden, wo etwas schief geht, anstatt überall hüpfen zu müssen.

Behandlung der gültigen und fehlerhaften Eingabe eines Tests

An dieser Stelle sollte klar sein, wie wir mit diesen Ausnahmen umgehen werden. Es gibt zwei Arten von Eingaben: gültige Eingabe und fehlerhafte Eingabe (die Eingabe ist im engeren Sinne gültig, aber nicht korrekt).

Wenn Sie mit gültigen Eingaben arbeiten , legen Sie die implizite Erwartung fest, dass jeder Test, den Sie schreiben, funktioniert.

Ein solcher Methodenaufruf kann folgendermaßen aussehen : existingUserById_ShouldReturn_UserObject. Wenn diese Methode fehlschlägt (z. B. eine Ausnahme wird ausgelöst), wissen Sie, dass ein Fehler aufgetreten ist, und können mit dem Graben beginnen.

Wenn Sie einen weiteren Test ( nonExistingUserById_ShouldThrow_IllegalArgumentException) hinzufügen , der die fehlerhafte Eingabe verwendet und eine Ausnahme erwartet, können Sie feststellen, ob Ihre Methode mit falschen Eingaben das tut, was sie tun soll.

TL; DR

Sie haben versucht, in Ihrem Test zwei Dinge zu tun: auf gültige und fehlerhafte Eingaben prüfen. Wenn Sie dies in zwei Methoden aufteilen, die jeweils eine Sache ausführen, erhalten Sie viel klarere Tests und einen viel besseren Überblick darüber, wo etwas schief geht.

Wenn Sie die geschichtete Arbeitseinheit berücksichtigen, können Sie auch die Anzahl der Tests reduzieren, die Sie für eine Ebene benötigen, die in der Hierarchie höher ist, da Sie nicht alles berücksichtigen müssen, was in den unteren Ebenen möglicherweise schief gelaufen ist: die Ebenen unterhalb der aktuellen Ebene sind eine virtuelle Garantie dafür, dass Ihre Abhängigkeiten funktionieren. Wenn etwas schief geht, befindet es sich in Ihrer aktuellen Ebene (vorausgesetzt, die unteren Ebenen werfen selbst keine Fehler).

Jeroen Vannevel
quelle
2
Die Sache ist, dass ich TDD versuche und einer der Mitarbeiter, die ich benutze, eine Ausnahme auslöst. Also muss ich die Tatsache testen, dass ich die vom Kollaborateur ausgelöste Ausnahme verbrauche
Ankit Dhingra
6
Wollen Sie damit sagen, dass Ihre Funktionalität von der Behandlung einer Ausnahme abhängt? Das ist ein Code-Geruch: Es gibt Ausnahmen, mit denen Sie Probleme elegant erkennen können. Sie werden nicht zur Flusskontrolle verwendet. Wenn Sie ein Szenario testen möchten, in dem eine Ausnahme ausgelöst werden soll, sollten Sie die expectedAnmerkung verwenden. Wenn Sie ein Szenario testen möchten, in dem Ihr Code fehlschlägt und Sie sehen möchten, ob der Fehler korrekt behandelt wird, expectedverwenden Sie Asserts, um festzustellen, ob er behoben wurde.
Jeroen Vannevel
Die Sache ist, dass ich mich nicht von der Ausnahme erholen kann, die im Collaborator aufgetreten ist, und alles, was ich tue, ist, das Problem nur mit einem log.debug ("Fehlermeldung") zu protokollieren. Es treten also keine Nebenwirkungen als Teil des Fangblocks auf, auf den ich möglicherweise hinweisen kann.
Ankit Dhingra
5
@JeroenVannevel Es ist absolut gültig zu testen, ob eine Fehlersituation, die dazu führt, dass eine Ausnahme ausgelöst wird, ordnungsgemäß behandelt wird.
Thorbjørn Ravn Andersen
1
@dpk ja du kannst. Sie fügen throws IllegalArgumentExceptionIhrem Test hinzu. Was Sie am Ende wollen, ist, dass Ihr Test rot wird, wenn es eine Ausnahme gibt. Rate mal? Sie müssen nicht schreiben fail(). Wie @Jeroen Vannevel schrieb: "Wenn eine Ausnahme ausgelöst wird,
Amedee Van Gasse
131

Ich bin darauf gestoßen, weil SonarQubes Regel "squid: S2699" lautet: "Fügen Sie diesem Testfall mindestens eine Behauptung hinzu."

Ich hatte einen einfachen Test, dessen einziges Ziel es war, ohne Ausnahmen durchzugehen.

Betrachten Sie diesen einfachen Code:

public class Printer {

    public static void printLine(final String line) {
        System.out.println(line);
    }
}

Welche Art von Behauptung kann hinzugefügt werden, um diese Methode zu testen? Sicher, Sie können es versuchen, aber das ist nur Code Bloat.

Die Lösung kommt von JUnit selbst.

Wenn keine Ausnahme ausgelöst wird und Sie dieses Verhalten explizit veranschaulichen möchten, fügen Sie es einfach expectedwie im folgenden Beispiel hinzu:

@Test(expected = Test.None.class /* no exception expected */)
public void test_printLine() {
    Printer.printLine("line");
}

Test.None.class ist die Standardeinstellung für den erwarteten Wert.

Sven Döring
quelle
30
Ich denke, das ist die beste Antwort. Die akzeptierte Antwort ist großartig und der Autor weist zu Recht auf den Codegeruch hin. Allerdings hat er die spezifische Frage nicht wirklich beantwortet.
HellishHeat
4
Es ist interessant festzustellen, dass der Standardwert für den erwarteten Wert None ist. Es reicht also aus, die Methode nur mit @Test zu kommentieren.
Oziomajnr
42

Mit AssertJ fließende Behauptungen 3.7.0 :

Assertions.assertThatCode(() -> toTest.method())
    .doesNotThrowAnyException();
denu
quelle
1
@emeraldhieu Bei der Frage geht es nicht einmal um assertJ. Wie beantwortet diese Frage "direkt" die Frage von OP?
MauriceNino
41

JUnit 5 (Jupiter) bietet drei Funktionen zum Überprüfen der Abwesenheit / Anwesenheit von Ausnahmen:

assertAll​()

Behauptet , dass alle gelieferten executables
  nicht Ausnahmen werfen.

assertDoesNotThrow​()

Behauptet , dass die Ausführung des
  gelieferten executable/ supplier
wirft nicht jede Art von Ausnahme .

  Diese Funktion ist
  seit JUnit 5.2.0 (29. April 2018) verfügbar .

assertThrows​()

Behauptet , dass die Ausführung des mitgelieferten executable
wirft eine Ausnahme der expectedType
  und gibt die Ausnahme .

Beispiel

package test.mycompany.myapp.mymodule;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class MyClassTest {

    @Test
    void when_string_has_been_constructed_then_myFunction_does_not_throw() {
        String myString = "this string has been constructed";
        assertAll(() -> MyClass.myFunction(myString));
    }

    @Test
    void when_string_has_been_constructed_then_myFunction_does_not_throw__junit_v520() {
        String myString = "this string has been constructed";
        assertDoesNotThrow(() -> MyClass.myFunction(myString));
    }

    @Test
    void when_string_is_null_then_myFunction_throws_IllegalArgumentException() {
        String myString = null;
        assertThrows(
            IllegalArgumentException.class,
            () -> MyClass.myFunction(myString));
    }

}
olibre
quelle
1
Dies ist jetzt die beste Antwort. Andere Antworten diskutieren ältere Versionen von JUnit
Tejesh Raut
29

Java 8 macht dies viel einfacher und Kotlin / Scala doppelt.

Wir können eine kleine Utility-Klasse schreiben

class MyAssertions{
  public static void assertDoesNotThrow(FailingRunnable action){
    try{
      action.run()
    }
    catch(Exception ex){
      throw new Error("expected action not to throw, but it did!", ex)
    }
  }
}

@FunctionalInterface interface FailingRunnable { void run() throws Exception }

und dann wird Ihr Code einfach:

@Test
public void foo(){
  MyAssertions.assertDoesNotThrow(() -> {
    //execute code that you expect not to throw Exceptions.
  }
}

Wenn Sie keinen Zugriff auf Java-8 haben, würde ich eine schmerzhaft alte Java-Funktion verwenden: Aribitrary-Code-Blöcke und einen einfachen Kommentar

//setup
Component component = new Component();

//act
configure(component);

//assert 
/*assert does not throw*/{
  component.doSomething();
}

Und schließlich mit Kotlin, einer Sprache, in die ich mich kürzlich verliebt habe:

fun (() -> Any?).shouldNotThrow() 
    = try { invoke() } catch (ex : Exception){ throw Error("expected not to throw!", ex) }

@Test fun `when foo happens should not throw`(){

  //...

  { /*code that shouldn't throw*/ }.shouldNotThrow()
}

Obwohl es viel Raum gibt, genau damit herumzuspielen, wie Sie dies ausdrücken möchten, war ich immer ein Fan von fließenden Behauptungen .


Hinsichtlich

Sie nähern sich dem falsch. Testen Sie einfach Ihre Funktionalität: Wenn eine Ausnahme ausgelöst wird, schlägt der Test automatisch fehl. Wenn keine Ausnahme ausgelöst wird, werden Ihre Tests alle grün angezeigt.

Dies ist im Prinzip richtig, aber in der Schlussfolgerung falsch.

Java erlaubt Ausnahmen für den Kontrollfluss. Dies erfolgt durch die JRE-Laufzeit selbst in APIs wie Double.parseDoubleüber a NumberFormatExceptionund Paths.getüber a InvalidPathException.

Wenn Sie eine Komponente geschrieben haben Double.ParseDouble, die Zahlenzeichenfolgen überprüft, z . B. mithilfe eines Regex, möglicherweise eines handgeschriebenen Parsers, oder wenn einige andere Domänenregeln eingebettet sind, die den Bereich eines Double auf etwas Bestimmtes beschränken, können Sie dies am besten testen Komponente? Ich denke, ein offensichtlicher Test wäre die Behauptung, dass beim Analysieren der resultierenden Zeichenfolge keine Ausnahme ausgelöst wird. Ich würde diesen Test entweder mit dem obigen assertDoesNotThrowoder dem /*comment*/{code}Block schreiben . Etwas wie

@Test public void given_validator_accepts_string_result_should_be_interpretable_by_doubleParseDouble(){
  //setup
  String input = "12.34E+26" //a string double with domain significance

  //act
  boolean isValid = component.validate(input)

  //assert -- using the library 'assertJ', my personal favourite 
  assertThat(isValid).describedAs(input + " was considered valid by component").isTrue();
  assertDoesNotThrow(() -> Double.parseDouble(input));
}

Ich würde empfehlen Ihnen , diesen Test zu parametrieren auf inputVerwendung Theoriesoder Parameterizedso dass Sie leichter für andere Eingänge diesen Test erneut verwenden. Wenn Sie exotisch werden möchten, können Sie sich alternativ für ein Tool zur Testgenerierung entscheiden (und dies ). TestNG bietet eine bessere Unterstützung für parametrisierte Tests.

Was ich besonders unangenehm finde, ist die Empfehlung der Verwendung @Test(expectedException=IllegalArgumentException.class), diese Ausnahme ist gefährlich weit gefasst . Wenn sich Ihr Code so ändert, dass die Komponente unter dem Konstruktor des Tests vorhanden ist if(constructorArgument <= 0) throw IllegalArgumentException(), und Ihr Test 0 für dieses Argument lieferte, weil es praktisch war - und dies ist sehr häufig, da das gute Generieren von Testdaten ein überraschend schwieriges Problem ist -, dann ist Ihr Test wird grün-Balken sein, obwohl es nichts testet. Ein solcher Test ist schlimmer als nutzlos.

Groostav
quelle
2
(in Bezug auf die Verwendung der erwarteten Ausnahme) Seit JUnit 4.13 können Sie Assert.assertThrowsüberprüfen, ob ein Code eine Ausnahme auslöst.
MageWind
22

Wenn Sie das Pech haben, alle Fehler in Ihrem Code zu erkennen. Das kannst du dumm machen

class DumpTest {
    Exception ex;
    @Test
    public void testWhatEver() {
        try {
            thisShouldThrowError();
        } catch (Exception e) {
            ex = e;
        }
        assertEquals(null,ex);
    }
}
Ben Tennyson
quelle
1
Nur ein kleiner Vorschlag, Exception exsollte sein, = null;bevor Sie es testen können.
Denees
4
Dies ist keine großartige Lösung. Wenn die Methode, die keine Ausnahme auslösen soll, ausgelöst wird, wird keine nützliche Fehlermeldung angezeigt. Rufen Sie einfach die Methode auf, die keine Ausnahme auslösen soll, und testen Sie den Rückgabewert (oder Nebenwirkungen wie das Protokollieren der Ausnahme). Wenn später unerwartet eine Ausnahme ausgelöst wird, schlägt der Test fehl.
NamshubWriter
3
Oder setzen Sie einfach Assert.fail () in den Fang, einfacher und hübscher IMO.
isaac.hazan
Ja, ich stimme dir zu. Eine weitere Möglichkeit ist das Hinzufügen einer Anmerkung über der Methode @Test (erwartet = InvalidRequestException.class)
Ben Tennyson
Ihre falsche Schreibweise ist verwirrend: thisShouldThroughError -> thisShouldThrowError .
Oscar Bravo
7

JUnit5 fügt genau zu diesem Zweck die assertAll () -Methode hinzu.

assertAll( () -> foo() )

Quelle: JUnit 5 API

Razalghul
quelle
7

Obwohl dieser Beitrag jetzt 6 Jahre alt ist, hat sich in der Junit-Welt viel geändert. Mit Junit5 können Sie jetzt verwenden

org.junit.jupiter.api.Assertions.assertDoesNotThrow()

Ex:

public void thisMethodDoesNotThrowException(){
   System.out.println("Hello There");
}

@Test
public void test_thisMethodDoesNotThrowException(){
  org.junit.jupiter.api.Assertions.assertDoesNotThrow(
      ()-> thisMethodDoesNotThrowException()
    );
}

Hoffe, es wird Menschen helfen, die eine neuere Version von Junit5 verwenden

Dinesh Arora
quelle
Ich wünschte, es gäbe eine Möglichkeit, hier eine konkrete Ausnahmeklasse anzugeben. Ich habe diese nach innen zu tun Awaitilityist untilAsserted(ThrowingRunnable assertion). Das zu testende System löst derzeit eine bestimmte Ausnahme für das von mir bereitgestellte ThrowingRunnable aus, aber ich möchte ihm etwas Zeit geben, bis es damit aufhört. Wenn es jedoch eine andere Ausnahme auslösen würde, möchte ich, dass der Test sofort fehlschlägt.
Ubeogesh
1

Wenn Sie testen möchten, ob Ihr Testziel die Ausnahme verwendet. Lassen Sie den Test einfach als (Mock Collaborator mit jMock2):

@Test
public void consumesAndLogsExceptions() throws Exception {

    context.checking(new Expectations() {
        {
            oneOf(collaborator).doSth();
            will(throwException(new NullPointerException()));
        }
    });

    target.doSth();
 }

Der Test würde bestanden, wenn Ihr Ziel die ausgelöste Ausnahme verbraucht, andernfalls würde der Test fehlschlagen.

Wenn Sie Ihre Ausnahmekonsumlogik testen möchten, werden die Dinge komplexer. Ich schlage vor, den Verbrauch an einen Mitarbeiter zu delegieren, der verspottet werden könnte. Daher könnte der Test sein:

@Test
public void consumesAndLogsExceptions() throws Exception {
    Exception e = new NullPointerException();
    context.checking(new Expectations() {
        {
            allowing(collaborator).doSth();
            will(throwException(e));

            oneOf(consumer).consume(e);
        }
    });

    target.doSth();
 }

Aber manchmal ist es überarbeitet, wenn Sie es nur protokollieren möchten. In diesem Fall ist dieser Artikel ( http://java.dzone.com/articles/monitoring-declarative-transac , http://blog.novoj.net/2008/09/20/testing-aspect-pointcuts-is-there) -an-easy-way / ) kann helfen, wenn Sie in diesem Fall auf tdd bestehen.

Yugang Zhou
quelle
1

Verwenden Sie assertNull (...)

@Test
public void foo() {
    try {
        //execute code that you expect not to throw Exceptions.
    } catch (Exception e){
        assertNull(e);
    }
}
Mike Rapadas
quelle
6
Ich würde sagen, das ist irreführend. Der catch-Block wird nie erreicht, daher assertNullwird er auch nie ausgeführt. Der schnelle Leser hat jedoch den Eindruck, dass eine Behauptung aufgestellt wird, die den nicht werfenden Fall wirklich bestätigt. Mit anderen Worten: Wenn der catch-Block erreicht ist, ist die Ausnahme immer ungleich Null - sie kann daher durch eine einfache ersetzt werden fail.
Andreas
in der Tat irreführend, ..... aber warte, ... oh ich verstehe ... assertNull(e)wird den Test als fehlgeschlagen melden, wie gesagt ekann nicht nullim catchBlock sein ... Mike das ist nur seltsame Programmierung: - /. .. ja zumindest verwenden fail()wie Andreas sagt
Julien
1

Sie können erwarten, dass eine Ausnahme nicht ausgelöst wird, indem Sie eine Regel erstellen.

@Rule
public ExpectedException expectedException = ExpectedException.none();
LazerBanana
quelle
ExpectedExceptions werden verwendet, um ausgelöste Ausnahmen zu aktivieren. Der von Ihnen angegebene Code dient lediglich zum Initialisieren der Regel, damit Sie Ihre Anforderungen für die Zusicherungen hinzufügen können. Dieser Code selbst bringt überhaupt keinen Wert. Das Javadoc gibt außerdem Folgendes an: "/ ** * Gibt eine {@linkplain TestRule-Regel} zurück, die erwartet, dass keine * Ausnahme ausgelöst wird (identisch mit dem Verhalten ohne diese Regel). * /" Es wird also genau das gleiche Ergebnis wie ohne diese Regel erzielt .
Pim Hazebroek
Ich stimme Ihnen zu und würde es nicht so verwenden, aber es ist möglich zu behaupten, dass keine Ausnahme ausgelöst wurde. Wenn der Test erfolgreich ist, sollte genug vorhanden sein, um zu sagen, dass die Ausnahme nicht ausgelöst wurde. Wenn jedoch eine Frage vorliegt, muss dies erforderlich sein. Und selten aber manchmal ist es gut, es sichtbar zu haben. Was ist, wenn sich Code und Umstände geändert haben und wir keinen Test für einen bestimmten Randfall haben?
LazerBanana
Ich bin gespannt, wie Sie das mit der erwarteten Ausnahme behaupten würden. Und ja, wenn sich die Anforderungen ändern und Sie keinen Test für ein bestimmtes Kantengehäuse haben, sind Sie verschraubt ;-) decken immer alle Eckgehäuse ab.
Pim Hazebroek
Was meinst du? Sie behaupten es nicht, Sie erwarten es. In diesem Fall erwarten Sie keine Ausnahme. Ich bin mir nicht sicher, worüber du redest.
LazerBanana
0

Dies ist möglicherweise nicht der beste Weg, stellt jedoch sicher, dass keine Ausnahme vom getesteten Codeblock ausgelöst wird.

import org.assertj.core.api.Assertions;
import org.junit.Test;

public class AssertionExample {

    @Test
    public void testNoException(){
        assertNoException();
    }    

    private void assertException(){
        Assertions.assertThatThrownBy(this::doNotThrowException).isInstanceOf(Exception.class);
    }

    private void assertNoException(){
        Assertions.assertThatThrownBy(() -> assertException()).isInstanceOf(AssertionError.class);
    }

    private void doNotThrowException(){
        //This method will never throw exception
    }
}
MLS
quelle
0

Sie können dies tun, indem Sie eine @Rule verwenden und dann die Methode reportMissingExceptionWithMessage aufrufen, wie unten gezeigt: Dies ist Scala-Code.

Geben Sie hier die Bildbeschreibung ein

Crenguta S.
quelle
1
private val? Welche Sprache ist das? Ganz klar nicht Java; p Und bitte geben Sie keinen Code als Screenshot an, er wird nicht begrüßt.
Andremoniy
Ich sehe, Sie haben erwähnt, dass es Scala ist, aber zu sagen, dass es leicht in Java gemacht werden kann, ist kein starkes Argument. Es tut mir leid
Andremoniy
Ich habe den Teil entfernt, der dich gestört hat. Ich werde versuchen, das Bild auch zu ersetzen. Ich habe noch nicht herausgefunden, wie man Code hinzufügt.
Crenguta S
-1

Folgendes führt den Test für alle aktivierten oder deaktivierten Ausnahmen nicht durch:

@Test
public void testMyCode() {

    try {
        runMyTestCode();
    } catch (Throwable t) {
        throw new Error("fail!");
    }
}
Rocky Inde
quelle
-1

Sie können jede Art von eigenen Aussagen erstellen, die auf Aussagen von junit basieren:

static void assertDoesNotThrow(Executable executable) {
    assertDoesNotThrow(executable, "must not throw");
}
static void assertDoesNotThrow(Executable executable, String message) {
    try {
        executable.execute();
    } catch (Throwable err) {
        fail(message);
    }
}

Und testen:

//the following will succeed
assertDoesNotThrow(()->methodMustNotThrow(1));
assertDoesNotThrow(()->methodMustNotThrow(1), "fail with specific message: facepalm");
//the following will fail
assertDoesNotThrow(()->methodMustNotThrow(2));
assertDoesNotThrow(()-> {throw new Exception("Hello world");}, "Fail: must not trow");

Im Allgemeinen besteht die Möglichkeit, den Test in jedem Szenario und an jedem Ort, an dem er sinnvoll ist, sofort zu bestehen ("bla bla bla"). Verwenden Sie es beispielsweise in einem Try / Catch-Block, um zu scheitern, wenn im Testfall etwas ausgelöst wird:

try{methodMustNotThrow(1);}catch(Throwable e){fail("must not throw");}
//or
try{methodMustNotThrow(1);}catch(Throwable e){Assertions.fail("must not throw");}

Dies ist das Beispiel der Methode, die wir testen, vorausgesetzt, wir haben eine solche Methode, die unter bestimmten Umständen nicht fehlschlagen darf, aber fehlschlagen kann:

void methodMustNotThrow(int x) throws Exception{
    if (x == 1) return;
    throw new Exception();
}

Die obige Methode ist ein einfaches Beispiel. Dies funktioniert jedoch in komplexen Situationen, in denen der Fehler nicht so offensichtlich ist. Es gibt die Importe:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import static org.junit.jupiter.api.Assertions.*;
armagedescu
quelle
Es gibt eine bessere Möglichkeit, um zu überprüfen, ob keine Zusicherung ausgelöst wurde, ohne dass benutzerdefinierter Code erstellt werden muss. @ Regel ist einer von ihnen
Vargan
@ Vargan Ich habe auf die Methode hingewiesen, mit der Sie Ihre eigenen Zusicherungen so erstellen können, wie sie von JUnit entworfen wurden, insbesondere um Ihre eigenen Zusicherungen zu erstellen. JUnit sieht vor, dass Sie das Verhalten von JUnit mit Asserts erweitern, die noch nicht implementiert sind, insbesondere zu diesem Zweck, um eigene Regeln zu erstellen. Weil nicht alles in dieser Welt implementiert ist. Diese Zusicherungen funktionieren genauso wie die JUnit-Zusicherung in Bezug auf Bestehen oder Nichtbestehen sowie das Melden von Fehlern.
armagedescu