Kurzanleitung zu BDDMockito

1. Überblick

BDD empfiehlt das Schreiben von Tests in einer natürlichen, vom Menschen lesbaren Sprache, die sich auf das Verhalten der Anwendung konzentriert.

Es definiert eine klar strukturierte Schreibweise von Tests in drei Abschnitten (Arrange, Act, Assert):

  • given einige Vorbedingungen (Arrangieren)

  • wenn eine Aktion erfolgt (Act)

  • then die Ausgabe überprüfen (Assert)

  • Die Mockito-Bibliothek wird mit einer BDDMockito -Klasse ausgeliefert, die BDD-freundliche APIs einführt. ** Mit dieser API können wir einen BDD-freundlicheren Ansatz verfolgen, indem wir unsere Tests mit given () anordnen und Assertions mit then () vornehmen.

In diesem Artikel erklären wir, wie Sie unsere BDD-basierten Mockito-Tests einrichten. Wir werden auch über die Unterschiede zwischen Mockito - und BDDMockito -APIs sprechen, um uns schließlich auf die BDDMockito -API zu konzentrieren.

2. Konfiguration

2.1. Abhängigkeiten von Maven

  • Die BDD-Variante von Mockito ist Teil der mockito-core -Bibliothek ** , um loslegen zu können, müssen wir nur das Artefakt einfügen:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.21.0</version>
</dependency>

Die neueste Version von Mockito finden Sie unter Maven Zentral .

2.2. Importe

Unsere Tests können besser lesbar werden, wenn wir den folgenden statischen Import verwenden:

import static org.mockito.BDDMockito.** ;

Beachten Sie, dass BDDMockito Mockito erweitert, so dass keine Funktionen fehlen, die von der traditionellen Mockito -API bereitgestellt werden.

3. Mockito vs. BDDMockito

Das traditionelle Mockito in Mockito wird mit when (obj) . und dann mit ** () im Arrangierschritt ausgeführt.

Später kann die Interaktion mit unserem Modell mit verify () im Assert-Schritt überprüft werden.

  • BDDMockito stellt BDD-Aliase für verschiedene Mockito -Methoden bereit, sodass wir unseren Arrange-Schritt mit given (anstelle von when ) schreiben können. Ebenso können wir unseren Assert-Schritt mit then (anstelle von verify ) schreiben. **

Schauen wir uns ein Beispiel eines Testkörpers an, der traditionelles Mockito verwendet:

when(phoneBookRepository.contains(momContactName))
  .thenReturn(false);

phoneBookService.register(momContactName, momPhoneNumber);

verify(phoneBookRepository)
  .insert(momContactName, momPhoneNumber);

Mal sehen, wie das mit BDDMockito verglichen wird:

given(phoneBookRepository.contains(momContactName))
  .willReturn(false);

phoneBookService.register(momContactName, momPhoneNumber);

then(phoneBookRepository)
  .should()
  .insert(momContactName, momPhoneNumber);

4. Verspotten mit BDDMockito

Versuchen wir den PhoneBookService zu testen, wo wir das __PhoneBookRepository nachahmen müssen:

public class PhoneBookService {
    private PhoneBookRepository phoneBookRepository;

    public void register(String name, String phone) {
        if(!name.isEmpty() && !phone.isEmpty()
          && !phoneBookRepository.contains(name)) {
            phoneBookRepository.insert(name, phone);
        }
    }

    public String search(String name) {
        if(!name.isEmpty() && phoneBookRepository.contains(name)) {
            return phoneBookRepository.getPhoneNumberByContactName(name);
        }
        return null;
    }
}

Mit BDDMockito als Mockito können wir einen Wert zurückgeben, der fest oder dynamisch ist. Es erlaubt uns auch, eine Ausnahme auszulösen:

4.1. Rückgabe eines festen Wertes

Mit __BDDMockito konnten wir Mockito problemlos so konfigurieren, dass ein festes Ergebnis zurückgegeben wird, wenn unsere Zielobjektmethode "Scheinobjekt" aufgerufen wird:

given(phoneBookRepository.contains(momContactName))
  .willReturn(false);

phoneBookService.register(xContactName, "");

then(phoneBookRepository)
  .should(never())
  .insert(momContactName, momPhoneNumber);

4.2. Dynamischen Wert zurückgeben

BDDMockito ermöglicht uns eine differenziertere Methode zur Rückgabe von Werten. Wir könnten ein dynamisches Ergebnis basierend auf der Eingabe zurückgeben:

given(phoneBookRepository.contains(momContactName))
  .willReturn(true);
given(phoneBookRepository.getPhoneNumberByContactName(momContactName))
  .will((InvocationOnMock invocation) ->
    invocation.getArgument(0).equals(momContactName)
      ? momPhoneNumber
      : null);
phoneBookService.search(momContactName);
then(phoneBookRepository)
  .should()
  .getPhoneNumberByContactName(momContactName);

4.3. Eine Ausnahme auslösen

Mockito zu sagen, dass er eine Ausnahme auslösen soll, ist ziemlich einfach:

given(phoneBookRepository.contains(xContactName))
  .willReturn(false);
willThrow(new RuntimeException())
  .given(phoneBookRepository)
  .insert(any(String.class), eq(tooLongPhoneNumber));

try {
    phoneBookService.register(xContactName, tooLongPhoneNumber);
    fail("Should throw exception");
} catch (RuntimeException ex) { }

then(phoneBookRepository)
  .should(never())
  .insert(momContactName, tooLongPhoneNumber);

Beachten Sie, wie wir die Positionen von given und will ** ausgetauscht haben. Dies ist zwingend, wenn wir eine Methode verspotten, die keinen Rückgabewert hat.

Beachten Sie auch, dass wir Argumentvergleicher wie ( any , eq ) verwendet haben, um eine allgemeinere Art des Spottens basierend auf Kriterien zu bieten, anstatt auf einem festen Wert zu beruhen.

5. Fazit

In diesem kurzen Tutorial haben wir diskutiert, wie BDDMockito versucht, unseren Mockito-Tests eine BDD-Ähnlichkeit zu verleihen, und wir haben einige Unterschiede zwischen Mockito und BDDMockito diskutiert.

Den Quellcode finden Sie wie immer unter https://github.com/eugenp/tutorials/tree/master/testing-modules/mockito Über GitHub]- im Testpaket com.baeldung.bddmockito .