Jakie jest rzeczywiste zastosowanie „niepowodzenia” w przypadku testowym JUnit?

123

Jakie jest rzeczywiste zastosowanie „niepowodzenia” w przypadku testowym JUnit?

Sanju
źródło

Odpowiedzi:

138

Niektóre przypadki, w których uznałem to za przydatne:

  • zaznacz test, który jest niekompletny, aby zakończył się niepowodzeniem i ostrzega, dopóki nie możesz go ukończyć
  • upewnienie się, że wyjątek został zgłoszony:
try{
  // do stuff...
  fail("Exception not thrown");
}catch(Exception e){
  assertTrue(e.hasSomeFlag());
}

Uwaga:

Od JUnit4 istnieje bardziej elegancki sposób sprawdzenia, czy wyjątek jest generowany: użyj adnotacji @Test(expected=IndexOutOfBoundsException.class)

Jednak to nie zadziała, jeśli chcesz również sprawdzić wyjątek, nadal potrzebujesz fail().

sleske
źródło
5
Rozważ ten post na blogu o względnych zaletach niepowodzenia w porównaniu z oczekiwanymi adnotacjami: blog.jooq.org/2016/01/20/...
lbalazscs
4
@sleske "jeśli chcesz również sprawdzić wyjątek, nadal potrzebujesz fail ()" - nie. ExpectedException to sposób, patrz github.com/junit-team/junit4/wiki/exception-testing
kraxor
@kraxor: To prawda, nie wiedziałem o tym, kiedy pisałem odpowiedź (prawdopodobnie wtedy jej nie było).
sleske
14

Powiedzmy, że piszesz przypadek testowy dla ujemnego przepływu, w którym testowany kod powinien zgłosić wyjątek.

try{
   bizMethod(badData);
   fail(); // FAIL when no exception is thrown
} catch (BizException e) {
   assert(e.errorCode == THE_ERROR_CODE_U_R_LOOKING_FOR)
}
kartheek
źródło
10

Myślę, że typowym przypadkiem użycia jest wywołanie tego, gdy żaden wyjątek nie został zgłoszony w teście negatywnym.

Coś w rodzaju następującego pseudokodu:

test_addNilThrowsNullPointerException()
{
    try {
        foo.add(NIL);                      // we expect a NullPointerException here
        fail("No NullPointerException");   // cause the test to fail if we reach this            
     } catch (NullNullPointerException e) {
        // OK got the expected exception
    }
}
filant
źródło
3
Jeśli nie zaznaczysz czegoś w bloku catch, możesz użyć adnotacji metody @ExpectedException (NullNullPointerException.class), aby zadeklarować, że oczekujesz wyjątku (specjalnego rodzaju).
FrVaBe
8

Użyłem go w przypadku, gdy coś mogło pójść nie tak w mojej metodzie @Before.

public Object obj;

@Before
public void setUp() {
    // Do some set up
    obj = new Object();
}

@Test
public void testObjectManipulation() {
    if(obj == null) {
        fail("obj should not be null");
     }

    // Do some other valuable testing
}
Ryan D.
źródło
1
Tak, warunki wstępne testowania są dobre. Jeśli jednak chcesz się upewnić, że @Beforemetoda się powiodła, prawdopodobnie lepiej sprawdzić to bezpośrednio w tej metodzie. Jako bonus, przynajmniej JUnit i TestNG zgłoszą nawet inną awarię dla błędów z @Before/ @AfterMethods, aby zobaczyć, że problem nie występował w samym teście.
sleske
4

W ten sposób używam metody Fail.

Istnieją trzy stany, w których może zakończyć się Twój przypadek testowy

  1. Powodzenie: testowana funkcja została wykonana pomyślnie i zwróciła dane zgodnie z oczekiwaniami
  2. Niezaliczone: testowana funkcja została wykonana pomyślnie, ale zwrócone dane nie były zgodne z oczekiwaniami
  3. Niepowodzenie: funkcja nie została wykonana pomyślnie, a tak się nie stało

zamierzone (w przeciwieństwie do negatywnych przypadków testowych, które spodziewają się wystąpienia wyjątku).

Jeśli używasz zaćmienia, trzy stany są oznaczone odpowiednio zielonym, niebieskim i czerwonym znacznikiem.

W trzecim scenariuszu używam operacji niepowodzenia.

np .: public Integer add (integer a, Integer b) {return new Integer (a.intValue () + b.intValue ())}

  1. Przypadek zaliczony: a = new Interger (1), b = new Integer (2), a funkcja zwróciła 3
  2. Przypadek nieprzekazany: a = new Interger (1), b = new Integer (2), a funkcja zwróciła wartość soem inną niż 3
  3. Niepowodzenie przypadku: a = null, b = null, a funkcja zgłasza wyjątek NullPointerException
user3044364
źródło
1
Jeśli spojrzysz na kod źródłowy JUnit, zobaczysz, że asercje używają fail().
Daniel C. Sobral
3

Ja na przykład używam fail()do wskazania testów, które jeszcze się nie zakończyły (zdarza się); w przeciwnym razie okazałyby się skuteczne.

Wynika to prawdopodobnie z faktu, że nie jestem świadomy jakiejś niepełnej () funkcjonalności, która istnieje w NUnit.

Alen Siljak
źródło
2

W ustawieniach współbieżnych i / lub asynchronicznych możesz chcieć sprawdzić, czy określone metody (np. Delegaci, detektory zdarzeń, programy obsługi odpowiedzi, możesz je nazwać) nie są wywoływane. Pomijając drwiące frameworki, możesz wywołaćfail() te metody, aby testy zakończyły się niepowodzeniem. Wygasłe limity czasu są kolejnym naturalnym stanem niepowodzenia w takich scenariuszach.

Na przykład:

final CountDownLatch latch = new CountDownLatch(1);

service.asyncCall(someParameter, new ResponseHandler<SomeType>() {
    @Override
    public void onSuccess(SomeType result) {
        assertNotNull(result);
        // Further test assertions on the result
        latch.countDown();
    }

    @Override
    public void onError(Exception e) {
        fail(exception.getMessage());
        latch.countDown();
    }
});

if ( !latch.await(5, TimeUnit.SECONDS) ) {
    fail("No response after 5s");
}
Raphael
źródło
0

Najważniejszym przypadkiem użycia jest prawdopodobnie sprawdzanie wyjątków.

Chociaż junit4 zawiera oczekiwany element do sprawdzania, czy wystąpił wyjątek, wygląda na to, że nie jest częścią nowszej junit5. Kolejną zaletą używania w fail()porównaniu z programem expectedjest to, że można go połączyć z finallyumożliwieniem czyszczenia przypadków testowych.

dao.insert(obj);
try {
  dao.insert(obj);
  fail("No DuplicateKeyException thrown.");
} catch (DuplicateKeyException e) {
  assertEquals("Error code doesn't match", 123, e.getErrorCode());
} finally {
  //cleanup
  dao.delete(obj);
}

Jak zauważono w innym komentarzu. Posiadanie testu, który kończy się niepowodzeniem do czasu zakończenia implementacji, również brzmi rozsądnie.

Udo Held
źródło