Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen Mockito | Testen von Backend-Anwendungen
Spring Boot Backend

bookMockito

Im vorherigen Kapitel haben wir uns daran erinnert, wie man Unit-Tests schreibt. In unserer Anwendung ist dies jedoch nicht immer praktisch, da das Testen eines Controllers das Testen des Service erfordert und das Testen des Service wiederum das Testen des Repository voraussetzt.

Diese Abhängigkeitskette wirft die Frage auf: Müssen wir alle Module und deren Abhängigkeiten testen, oder können wir ihr Verhalten simulieren – also sie mocken?

Mockito: Einführung

Mockito ist eine beliebte Bibliothek für Java, die verwendet wird, um Mock-Objekte in Unit-Tests zu erstellen.

Sie ermöglicht es Entwicklern, das Verhalten komplexer externer Abhängigkeiten (wie Datenbanken, Services oder APIs) zu simulieren, um die Logik einer bestimmten Komponente (in der Regel einer Klasse oder Methode) isoliert und getrennt zu testen, ohne mit diesen externen Systemen zu interagieren.

Dies macht Unit-Tests vorhersehbarer und schneller, da während des Testens keine echten Aufrufe an externe Ressourcen erforderlich sind.

Mock-Objekte in Mockito

Dies ermöglicht Entwicklern, sicherzustellen, dass die zu testende Komponente (die Einheit) korrekt funktioniert, ohne auf echte Abhängigkeiten wie Datenbanken oder externe Dienste angewiesen zu sein.

Eine Klasse kann mit @Mock annotiert werden, um eine Mock-Version zu erstellen. Diese Annotation wird häufig zusammen mit @InjectMocks verwendet, um Abhängigkeiten automatisch in die zu testende Klasse zu injizieren.

@Mock 
private MyService myServiceMock;

Dieses Mock-Objekt kann anschließend als Abhängigkeit mithilfe der Annotation @InjectMocks in ein anderes Objekt injektiert werden. Diese Annotation injiziert automatisch die Mock-Objekte in die zu testende Klasse.

@InjectMocks
private MyController myController;

Wichtige Methoden in Mockito

Mockito stellt eine Vielzahl von Methoden zur Verwaltung von Mock-Objekten bereit, wobei jede einen bestimmten Zweck im Testprozess erfüllt. Nachfolgend sind die wichtigsten Methoden mit ihren Erklärungen aufgeführt.

Testen von Controllern mit Mockito

Das Testen von Controllern beinhaltet häufig den Einsatz von Mocks für Services, die innerhalb des Controllers aufgerufen werden. In diesem Zusammenhang spielt Mockito eine zentrale Rolle, um die Logik des Controllers von der Service-Schicht zu isolieren.

Kurze Zusammenfassung des Videos

Wir testen Controller mit der Klasse MockMvc, aber was bietet sie und welche Vorteile ergeben sich daraus?

@Autowired
private MockMvc mockMvc;

Mit MockMvc können verschiedene HTTP-Anfragen (GET, POST, PUT usw.) simuliert werden. Es ist möglich, Parameter und Header zu übergeben sowie Antworten, Statuscodes, Header und Antwortinhalte zu überprüfen, was das Unit-Testing von Controllern deutlich vereinfacht.

Beispielsweise können Methoden wie perform() verwendet werden, um die Anfrage auszuführen, andExpect(), um die erwarteten Ergebnisse zu überprüfen, und content(), um den Inhalt der Antwort zu prüfen.

Test.java

Test.java

copy
1234
mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isOk())

Zusätzlich können Sie Assertions verketten, um den HTTP-Status mit status().isOk() zu überprüfen, JSON-Antwortstrukturen mit jsonPath() zu verifizieren und mehr.

Test.java

Test.java

copy
1234
.andExpect(jsonPath("$.id").value(bookResponseDTO.getId())) .andExpect(jsonPath("$.name").value(bookResponseDTO.getName())) .andExpect(jsonPath("$.author").value(bookResponseDTO.getAuthor())) .andExpect(jsonPath("$.price").value(bookResponseDTO.getPrice()));

Diese Werkzeuge ermöglichen eine umfassende Überprüfung des Controller-Verhaltens, ohne tatsächlich echte HTTP-Aufrufe durchzuführen.

Wichtige Annotationen

Die Annotation @WebMvcTest(BookController.class) wird zum Testen des BookController verwendet und lädt nur die Komponenten, die für diesen spezifischen Controller erforderlich sind. Sie schließt den Rest der Spring-Infrastruktur aus, sodass der Fokus auf dem Testen des Controllers selbst liegt.

@WebMvcTest(BookController.class)
public class BookControllerTest 

Zusätzlich erstellt die @MockBean-Annotation, die auf das bookService-Feld angewendet wird, eine Mock-Version des Service, sodass Sie dessen Verhalten simulieren können. Dies hilft, den Controller von seinen Abhängigkeiten zu isolieren und sich auf das Testen seiner Logik zu konzentrieren.

@MockBean
private BookService bookService;

Tests für die Methode updateBook

Wir haben zwei Tests für die updateBook-Methode geschrieben, die alle möglichen Fälle für diese Methode abdecken. Im ersten Test überprüfen wir, dass alles erfolgreich war und dass unsere Entität aktualisiert wurde.

BookControllerTest.java

BookControllerTest.java

copy
1234567891011121314151617
@Test void testUpdateBook_whenBookExists_shouldReturnUpdatedBook() throws Exception { String bookId = "1"; when(bookService.updateBook(bookId, bookRequestDTO)).thenReturn(bookResponseDTO); mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(bookResponseDTO.getId())) .andExpect(jsonPath("$.name").value(bookResponseDTO.getName())) .andExpect(jsonPath("$.author").value(bookResponseDTO.getAuthor())) .andExpect(jsonPath("$.price").value(bookResponseDTO.getPrice())); verify(bookService).updateBook(bookId, bookRequestDTO); }

Dieser Test überprüft das erfolgreiche Aktualisieren eines book, sofern es in der Datenbank vorhanden ist. Die Methode updateBook() des Service wird mit der Id des Buches und einem bookRequestDTO-Objekt aufgerufen. Anschließend gibt sie ein bookResponseDTO-Objekt zurück, das das aktualisierte Buch repräsentiert.

Überprüfung der Ausnahmebehandlung

Es gibt ebenfalls einen Test, bei dem im updateBook eine Ausnahme auftritt. Hierbei muss überprüft werden, wie sich der Controller in dieser Situation verhält.

BookControllerTest.java

BookControllerTest.java

copy
12345678910111213141516
@Test void testUpdateBook_whenBookNotFound_shouldReturnApiException() throws Exception { String bookId = "1"; String errorMessage = "ID not found"; when(bookService.updateBook(bookId, bookRequestDTO)) .thenThrow(new ApiException(errorMessage, HttpStatus.NOT_FOUND)); mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isNotFound()) .andExpect(jsonPath("$.error").value(errorMessage)); verify(bookService).updateBook(bookId, bookRequestDTO); }

Dieser Test überprüft das Verhalten des Controllers, wenn versucht wird, ein Buch zu aktualisieren, das nicht in der Datenbank gefunden wird. Die Methode updateBook() des Service wird zunächst mit der Id des Buches und einem bookRequestDTO-Objekt aufgerufen.

Statt eines erfolgreichen Ergebnisses wirft der Service jedoch eine ApiException, die darauf hinweist, dass das Buch mit der angegebenen Id nicht gefunden wurde.

Servicetests mit Mockito

Beim Testen eines Service ist es wichtig, diesen von Abhängigkeiten wie Repositories oder externen APIs zu isolieren. Mockito ermöglicht das Erstellen von Mocks für diese Abhängigkeiten und das Definieren ihres Verhaltens in den Tests.

Kurze Zusammenfassung des Videos

Zunächst erfolgt ein Test der Methode bei einer erfolgreichen Aktualisierung der Daten, das heißt, die Id ist gültig. Selbstverständlich wird Mockito verwendet, um das Verhalten des Repositorys zu mocken.

BookServiceTest.java

BookServiceTest.java

copy
123456789101112131415161718192021222324252627282930313233
@Test void testUpdateBook_whenBookExists_shouldUpdateAndReturnBook() { BookRequestDTO bookRequestDTO = new BookRequestDTO(); bookRequestDTO.setName("Updated Name"); bookRequestDTO.setAuthor("Updated Author"); bookRequestDTO.setPrice("150"); Book bookWithRepository = new Book(); bookWithRepository.setId("1"); bookWithRepository.setName("Original Name"); bookWithRepository.setAuthor("Original Author"); bookWithRepository.setPrice("100"); Book updateBook = new Book(); updateBook.setId("1"); updateBook.setName("Updated Name"); updateBook.setAuthor("Updated Author"); updateBook.setPrice("150"); when(bookRepository.findById("1")).thenReturn(Optional.of(bookWithRepository)); when(bookRepository.save(bookWithRepository)).thenReturn(updateBook); BookResponseDTO result = bookService.updateBook("1", bookRequestDTO); assertNotNull(result); assertEquals("1", result.getId()); assertEquals("Updated Name", result.getName()); assertEquals("Updated Author", result.getAuthor()); assertEquals("150", result.getPrice()); verify(bookRepository).findById("1"); verify(bookRepository).save(bookWithRepository); }

Die Methode bookRepository.findById("1") wird gemockt, um ein vorhandenes Book aus dem Repository zurückzugeben, und bookRepository.save(bookWithRepository) wird gemockt, um das aktualisierte Buch nach dem Speichern der Änderungen zurückzugeben.

Die Servicemethode updateBook() wird aufgerufen, um das Buch basierend auf dem bookRequestDTO zu aktualisieren und gibt ein BookResponseDTO zurück.

assertNotNull(result) stellt sicher, dass das Ergebnis nicht null ist, was auf eine erfolgreiche Aktualisierung hinweist, während assertEquals() überprüft, dass die ID, der name, der author und der price des aktualisierten Buchs den erwarteten Werten entsprechen.

 assertNotNull(result);
 assertEquals("1", result.getId());
 assertEquals("Updated Name", result.getName());
 assertEquals("Updated Author", result.getAuthor());
 assertEquals("150", result.getPrice());

Abschließend stellt verify() sicher, dass findById() und save() im Repository mit den korrekten Parametern aufgerufen wurden.

verify(bookRepository).findById("1");
verify(bookRepository).save(bookWithRepository);

Überprüfung einer Ausnahme in der Service-Schicht

Dieser Test prüft, ob der Service eine ApiException auslöst, wenn das zu aktualisierende Book nicht in der Datenbank gefunden wird.

BookServiceTest.java

BookServiceTest.java

copy
1234567891011121314151617181920
@Test void testUpdateBook_whenBookNotFound_shouldThrowApiException() { BookRequestDTO bookRequestDTO = new BookRequestDTO(); bookRequestDTO.setName("Updated Name"); bookRequestDTO.setAuthor("Updated Author"); bookRequestDTO.setPrice("150"); String idTest = "999"; when(bookRepository.findById(idTest)).thenReturn(Optional.empty()); ApiException apiException = assertThrows(ApiException.class, () -> { bookService.updateBook(idTest, bookRequestDTO); }); assertEquals("Not found book by id: " + idTest, apiException.getMessage()); assertEquals(HttpStatus.NOT_FOUND, apiException.getHttpStatus()); verify(bookRepository, never()).save(any(Book.class)); }

Zunächst wird ein BookRequestDTO-Objekt mit den Daten für die Aktualisierung erstellt, und eine Testbuch-Id, die nicht in der Datenbank existiert ("999"), wird zugewiesen. Die Methode bookRepository.findById(idTest) wird gemockt, um Optional.empty() zurückzugeben, was anzeigt, dass kein Buch mit dieser Id vorhanden ist.

when(bookRepository.findById(idTest)).thenReturn(Optional.empty());

Der Test verwendet die Methode assertThrows(), um zu prüfen, dass beim Aufruf von bookService.updateBook(idTest, bookRequestDTO) eine ApiException ausgelöst wird.

Anschließend verifizieren die Methoden assertEquals(), dass die Fehlermeldung der erwarteten Nachricht entspricht und der Fehlerstatus gleich HttpStatus.NOT_FOUND ist.

ApiException apiException = assertThrows(ApiException.class, () -> {
      bookService.updateBook(idTest, bookRequestDTO);
});

assertEquals("Not found book by id: " + idTest, apiException.getMessage());
assertEquals(HttpStatus.NOT_FOUND, apiException.getHttpStatus());

Die Methode verify(bookRepository, never()).save(any(Book.class)) stellt sicher, dass die Methode save() nicht aufgerufen wurde, da das Buch nicht gefunden wurde und die Aktualisierung nicht durchgeführt wurde.

verify(bookRepository, never()).save(any(Book.class));

Zusammenfassung

Mockito ist eine Bibliothek zur Erstellung von Mock-Objekten, die es ermöglicht, das Verhalten von Abhängigkeiten zu simulieren und den zu testenden Code zu isolieren. Dies vereinfacht das Testen, macht es schneller, stabiler und unabhängig von externen Ressourcen.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 5. Kapitel 3

Fragen Sie AI

expand

Fragen Sie AI

ChatGPT

Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen

Suggested prompts:

What are some common mistakes to avoid when using Mockito?

Can you explain the difference between @Mock and @MockBean?

How do I decide when to use mocks versus real objects in my tests?

Awesome!

Completion rate improved to 3.45

bookMockito

Swipe um das Menü anzuzeigen

Im vorherigen Kapitel haben wir uns daran erinnert, wie man Unit-Tests schreibt. In unserer Anwendung ist dies jedoch nicht immer praktisch, da das Testen eines Controllers das Testen des Service erfordert und das Testen des Service wiederum das Testen des Repository voraussetzt.

Diese Abhängigkeitskette wirft die Frage auf: Müssen wir alle Module und deren Abhängigkeiten testen, oder können wir ihr Verhalten simulieren – also sie mocken?

Mockito: Einführung

Mockito ist eine beliebte Bibliothek für Java, die verwendet wird, um Mock-Objekte in Unit-Tests zu erstellen.

Sie ermöglicht es Entwicklern, das Verhalten komplexer externer Abhängigkeiten (wie Datenbanken, Services oder APIs) zu simulieren, um die Logik einer bestimmten Komponente (in der Regel einer Klasse oder Methode) isoliert und getrennt zu testen, ohne mit diesen externen Systemen zu interagieren.

Dies macht Unit-Tests vorhersehbarer und schneller, da während des Testens keine echten Aufrufe an externe Ressourcen erforderlich sind.

Mock-Objekte in Mockito

Dies ermöglicht Entwicklern, sicherzustellen, dass die zu testende Komponente (die Einheit) korrekt funktioniert, ohne auf echte Abhängigkeiten wie Datenbanken oder externe Dienste angewiesen zu sein.

Eine Klasse kann mit @Mock annotiert werden, um eine Mock-Version zu erstellen. Diese Annotation wird häufig zusammen mit @InjectMocks verwendet, um Abhängigkeiten automatisch in die zu testende Klasse zu injizieren.

@Mock 
private MyService myServiceMock;

Dieses Mock-Objekt kann anschließend als Abhängigkeit mithilfe der Annotation @InjectMocks in ein anderes Objekt injektiert werden. Diese Annotation injiziert automatisch die Mock-Objekte in die zu testende Klasse.

@InjectMocks
private MyController myController;

Wichtige Methoden in Mockito

Mockito stellt eine Vielzahl von Methoden zur Verwaltung von Mock-Objekten bereit, wobei jede einen bestimmten Zweck im Testprozess erfüllt. Nachfolgend sind die wichtigsten Methoden mit ihren Erklärungen aufgeführt.

Testen von Controllern mit Mockito

Das Testen von Controllern beinhaltet häufig den Einsatz von Mocks für Services, die innerhalb des Controllers aufgerufen werden. In diesem Zusammenhang spielt Mockito eine zentrale Rolle, um die Logik des Controllers von der Service-Schicht zu isolieren.

Kurze Zusammenfassung des Videos

Wir testen Controller mit der Klasse MockMvc, aber was bietet sie und welche Vorteile ergeben sich daraus?

@Autowired
private MockMvc mockMvc;

Mit MockMvc können verschiedene HTTP-Anfragen (GET, POST, PUT usw.) simuliert werden. Es ist möglich, Parameter und Header zu übergeben sowie Antworten, Statuscodes, Header und Antwortinhalte zu überprüfen, was das Unit-Testing von Controllern deutlich vereinfacht.

Beispielsweise können Methoden wie perform() verwendet werden, um die Anfrage auszuführen, andExpect(), um die erwarteten Ergebnisse zu überprüfen, und content(), um den Inhalt der Antwort zu prüfen.

Test.java

Test.java

copy
1234
mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isOk())

Zusätzlich können Sie Assertions verketten, um den HTTP-Status mit status().isOk() zu überprüfen, JSON-Antwortstrukturen mit jsonPath() zu verifizieren und mehr.

Test.java

Test.java

copy
1234
.andExpect(jsonPath("$.id").value(bookResponseDTO.getId())) .andExpect(jsonPath("$.name").value(bookResponseDTO.getName())) .andExpect(jsonPath("$.author").value(bookResponseDTO.getAuthor())) .andExpect(jsonPath("$.price").value(bookResponseDTO.getPrice()));

Diese Werkzeuge ermöglichen eine umfassende Überprüfung des Controller-Verhaltens, ohne tatsächlich echte HTTP-Aufrufe durchzuführen.

Wichtige Annotationen

Die Annotation @WebMvcTest(BookController.class) wird zum Testen des BookController verwendet und lädt nur die Komponenten, die für diesen spezifischen Controller erforderlich sind. Sie schließt den Rest der Spring-Infrastruktur aus, sodass der Fokus auf dem Testen des Controllers selbst liegt.

@WebMvcTest(BookController.class)
public class BookControllerTest 

Zusätzlich erstellt die @MockBean-Annotation, die auf das bookService-Feld angewendet wird, eine Mock-Version des Service, sodass Sie dessen Verhalten simulieren können. Dies hilft, den Controller von seinen Abhängigkeiten zu isolieren und sich auf das Testen seiner Logik zu konzentrieren.

@MockBean
private BookService bookService;

Tests für die Methode updateBook

Wir haben zwei Tests für die updateBook-Methode geschrieben, die alle möglichen Fälle für diese Methode abdecken. Im ersten Test überprüfen wir, dass alles erfolgreich war und dass unsere Entität aktualisiert wurde.

BookControllerTest.java

BookControllerTest.java

copy
1234567891011121314151617
@Test void testUpdateBook_whenBookExists_shouldReturnUpdatedBook() throws Exception { String bookId = "1"; when(bookService.updateBook(bookId, bookRequestDTO)).thenReturn(bookResponseDTO); mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(bookResponseDTO.getId())) .andExpect(jsonPath("$.name").value(bookResponseDTO.getName())) .andExpect(jsonPath("$.author").value(bookResponseDTO.getAuthor())) .andExpect(jsonPath("$.price").value(bookResponseDTO.getPrice())); verify(bookService).updateBook(bookId, bookRequestDTO); }

Dieser Test überprüft das erfolgreiche Aktualisieren eines book, sofern es in der Datenbank vorhanden ist. Die Methode updateBook() des Service wird mit der Id des Buches und einem bookRequestDTO-Objekt aufgerufen. Anschließend gibt sie ein bookResponseDTO-Objekt zurück, das das aktualisierte Buch repräsentiert.

Überprüfung der Ausnahmebehandlung

Es gibt ebenfalls einen Test, bei dem im updateBook eine Ausnahme auftritt. Hierbei muss überprüft werden, wie sich der Controller in dieser Situation verhält.

BookControllerTest.java

BookControllerTest.java

copy
12345678910111213141516
@Test void testUpdateBook_whenBookNotFound_shouldReturnApiException() throws Exception { String bookId = "1"; String errorMessage = "ID not found"; when(bookService.updateBook(bookId, bookRequestDTO)) .thenThrow(new ApiException(errorMessage, HttpStatus.NOT_FOUND)); mockMvc.perform(put("/books/{id}", bookId) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(bookRequestDTO))) .andExpect(status().isNotFound()) .andExpect(jsonPath("$.error").value(errorMessage)); verify(bookService).updateBook(bookId, bookRequestDTO); }

Dieser Test überprüft das Verhalten des Controllers, wenn versucht wird, ein Buch zu aktualisieren, das nicht in der Datenbank gefunden wird. Die Methode updateBook() des Service wird zunächst mit der Id des Buches und einem bookRequestDTO-Objekt aufgerufen.

Statt eines erfolgreichen Ergebnisses wirft der Service jedoch eine ApiException, die darauf hinweist, dass das Buch mit der angegebenen Id nicht gefunden wurde.

Servicetests mit Mockito

Beim Testen eines Service ist es wichtig, diesen von Abhängigkeiten wie Repositories oder externen APIs zu isolieren. Mockito ermöglicht das Erstellen von Mocks für diese Abhängigkeiten und das Definieren ihres Verhaltens in den Tests.

Kurze Zusammenfassung des Videos

Zunächst erfolgt ein Test der Methode bei einer erfolgreichen Aktualisierung der Daten, das heißt, die Id ist gültig. Selbstverständlich wird Mockito verwendet, um das Verhalten des Repositorys zu mocken.

BookServiceTest.java

BookServiceTest.java

copy
123456789101112131415161718192021222324252627282930313233
@Test void testUpdateBook_whenBookExists_shouldUpdateAndReturnBook() { BookRequestDTO bookRequestDTO = new BookRequestDTO(); bookRequestDTO.setName("Updated Name"); bookRequestDTO.setAuthor("Updated Author"); bookRequestDTO.setPrice("150"); Book bookWithRepository = new Book(); bookWithRepository.setId("1"); bookWithRepository.setName("Original Name"); bookWithRepository.setAuthor("Original Author"); bookWithRepository.setPrice("100"); Book updateBook = new Book(); updateBook.setId("1"); updateBook.setName("Updated Name"); updateBook.setAuthor("Updated Author"); updateBook.setPrice("150"); when(bookRepository.findById("1")).thenReturn(Optional.of(bookWithRepository)); when(bookRepository.save(bookWithRepository)).thenReturn(updateBook); BookResponseDTO result = bookService.updateBook("1", bookRequestDTO); assertNotNull(result); assertEquals("1", result.getId()); assertEquals("Updated Name", result.getName()); assertEquals("Updated Author", result.getAuthor()); assertEquals("150", result.getPrice()); verify(bookRepository).findById("1"); verify(bookRepository).save(bookWithRepository); }

Die Methode bookRepository.findById("1") wird gemockt, um ein vorhandenes Book aus dem Repository zurückzugeben, und bookRepository.save(bookWithRepository) wird gemockt, um das aktualisierte Buch nach dem Speichern der Änderungen zurückzugeben.

Die Servicemethode updateBook() wird aufgerufen, um das Buch basierend auf dem bookRequestDTO zu aktualisieren und gibt ein BookResponseDTO zurück.

assertNotNull(result) stellt sicher, dass das Ergebnis nicht null ist, was auf eine erfolgreiche Aktualisierung hinweist, während assertEquals() überprüft, dass die ID, der name, der author und der price des aktualisierten Buchs den erwarteten Werten entsprechen.

 assertNotNull(result);
 assertEquals("1", result.getId());
 assertEquals("Updated Name", result.getName());
 assertEquals("Updated Author", result.getAuthor());
 assertEquals("150", result.getPrice());

Abschließend stellt verify() sicher, dass findById() und save() im Repository mit den korrekten Parametern aufgerufen wurden.

verify(bookRepository).findById("1");
verify(bookRepository).save(bookWithRepository);

Überprüfung einer Ausnahme in der Service-Schicht

Dieser Test prüft, ob der Service eine ApiException auslöst, wenn das zu aktualisierende Book nicht in der Datenbank gefunden wird.

BookServiceTest.java

BookServiceTest.java

copy
1234567891011121314151617181920
@Test void testUpdateBook_whenBookNotFound_shouldThrowApiException() { BookRequestDTO bookRequestDTO = new BookRequestDTO(); bookRequestDTO.setName("Updated Name"); bookRequestDTO.setAuthor("Updated Author"); bookRequestDTO.setPrice("150"); String idTest = "999"; when(bookRepository.findById(idTest)).thenReturn(Optional.empty()); ApiException apiException = assertThrows(ApiException.class, () -> { bookService.updateBook(idTest, bookRequestDTO); }); assertEquals("Not found book by id: " + idTest, apiException.getMessage()); assertEquals(HttpStatus.NOT_FOUND, apiException.getHttpStatus()); verify(bookRepository, never()).save(any(Book.class)); }

Zunächst wird ein BookRequestDTO-Objekt mit den Daten für die Aktualisierung erstellt, und eine Testbuch-Id, die nicht in der Datenbank existiert ("999"), wird zugewiesen. Die Methode bookRepository.findById(idTest) wird gemockt, um Optional.empty() zurückzugeben, was anzeigt, dass kein Buch mit dieser Id vorhanden ist.

when(bookRepository.findById(idTest)).thenReturn(Optional.empty());

Der Test verwendet die Methode assertThrows(), um zu prüfen, dass beim Aufruf von bookService.updateBook(idTest, bookRequestDTO) eine ApiException ausgelöst wird.

Anschließend verifizieren die Methoden assertEquals(), dass die Fehlermeldung der erwarteten Nachricht entspricht und der Fehlerstatus gleich HttpStatus.NOT_FOUND ist.

ApiException apiException = assertThrows(ApiException.class, () -> {
      bookService.updateBook(idTest, bookRequestDTO);
});

assertEquals("Not found book by id: " + idTest, apiException.getMessage());
assertEquals(HttpStatus.NOT_FOUND, apiException.getHttpStatus());

Die Methode verify(bookRepository, never()).save(any(Book.class)) stellt sicher, dass die Methode save() nicht aufgerufen wurde, da das Buch nicht gefunden wurde und die Aktualisierung nicht durchgeführt wurde.

verify(bookRepository, never()).save(any(Book.class));

Zusammenfassung

Mockito ist eine Bibliothek zur Erstellung von Mock-Objekten, die es ermöglicht, das Verhalten von Abhängigkeiten zu simulieren und den zu testenden Code zu isolieren. Dies vereinfacht das Testen, macht es schneller, stabiler und unabhängig von externen Ressourcen.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 5. Kapitel 3
some-alt