Im ersten Artikel dieser Serie haben wir den Aufbau eines robusten Bild-Uploaders mit Spring Boot, Cloudinary, Docker und PostgreSQL erläutert. Wir haben alles abgedeckt, von der Einrichtung des Projekts über das Senden von Anfragen bis hin zum Endpunkt, der das Bild und die Informationen speichert. Wenn Sie diesen Artikel noch nicht gelesen haben, empfehle ich Ihnen dringend, dort zu beginnen, um eine solide Grundlage für die Anwendung zu erhalten, mit der wir arbeiten werden.
Jetzt ist es an der Zeit sicherzustellen, dass unsere Anwendung zuverlässig ist und ihre Integrität im Laufe der Zeit beibehält. Dies bringt uns zu einem entscheidenden Aspekt der Softwareentwicklung: Testen. In diesem Artikel konzentrieren wir uns auf das Schreiben von Unit-Tests für unsere Bild-Uploader-API. Wir werden untersuchen, wie man Abhängigkeiten simuliert und Tests schreibt, die verschiedene Teile unseres Dienstes abdecken.
Unit-Tests helfen nicht nur, Fehler frühzeitig zu erkennen, sondern stellen auch sicher, dass unser Code wartbar und skalierbar ist. Am Ende dieses Artikels verfügen Sie über eine umfassende Reihe von Tests für Ihre Bild-Uploader-API, die Ihnen die Gewissheit geben, dass Ihre Anwendung wie erwartet funktioniert.
Lassen Sie uns in die Welt des Unit-Tests eintauchen und unsere Bild-Uploader-API kugelsicher machen!
Ich verwende VSCode mit dem Extension Pack für Java. Jetzt sind wir bereit, unsere Tests zu schreiben.
Wenn Sie eine andere IDE verwenden, finden Sie die Unterstützung für alle hier in der JUnit5-Dokumentation.
Klicken Sie mit der rechten Maustaste auf die Klasse „BookService“, klicken Sie auf „Gehe zu Test“ und wählen Sie im Menü die Methoden aus, für die Sie Tests generieren möchten.
Eine ähnliche Datei wie die folgende wird generiert:
import org.junit.jupiter.api.Test; public class BookServiceTest { @Test void testAddBook() { } }
Denken Sie daran, dass wir für diesen Artikel das AAA-Muster des Testens (Anordnen – Handeln – Bestätigen) verwenden werden.
@ExtendWith(MockitoExtension.class) public class BookServiceTest { @Mock private BookRepository bookRepository; @Mock private Cloudinary cloudinary; @Mock private MultipartFile multipartFile; @Mock private Uploader uploader; @Captor private ArgumentCaptor<Book> bookArgumentCaptor; @InjectMocks private BookService bookService; }
@ExtendWith(MockitoExtension.class) public class BookServiceTest { @Mock private BookRepository bookRepository; @Mock private Cloudinary cloudinary; @Mock private MultipartFile multipartFile; @Mock private Uploader uploader; @Captor private ArgumentCaptor<Book> bookArgumentCaptor; @InjectMocks private BookService bookService; @Nested class AddBook { @Test void shouldCreateANewBook() throws Exception { // Arrange Map<String, Object> uploadResult = Map.of("url", "http://example.com/image.jpg"); when(cloudinary.uploader()).thenReturn(uploader); when(uploader.upload(any(File.class), anyMap())).thenReturn(uploadResult); Book book = new Book(); book.setName("Test Book"); book.setImgUrl(uploadResult.get("url").toString()); when(bookRepository.save(any(Book.class))).thenReturn(book); when(multipartFile.getOriginalFilename()).thenReturn("test.jpg"); when(multipartFile.getBytes()).thenReturn("test content".getBytes()); // Act Book result = bookService.addBook("Test Book", multipartFile); // Assert assertNotNull(result); assertEquals("Test Book", result.getName()); assertEquals("http://example.com/image.jpg", result.getImgUrl()); } @Test void shouldCallRepositorySave() throws Exception { // Arrange Map<String, Object> uploadResult = Map.of("url", "http://example.com/image.jpg"); when(cloudinary.uploader()).thenReturn(uploader); when(uploader.upload(any(File.class), anyMap())).thenReturn(uploadResult); Book book = new Book(); book.setName("Test Book"); book.setImgUrl(uploadResult.get("url").toString()); when(bookRepository.save(any(Book.class))).thenReturn(book); when(multipartFile.getOriginalFilename()).thenReturn("test.jpg"); when(multipartFile.getBytes()).thenReturn("test content".getBytes()); // Act bookService.addBook("Test Book", multipartFile); // Assert verify(bookRepository, times(1)).save(bookArgumentCaptor.capture()); Book capturedBook = bookArgumentCaptor.getValue(); assertEquals("Test Book", capturedBook.getName()); assertEquals("http://example.com/image.jpg", capturedBook.getImgUrl()); } @Test void shouldFailTheUpload() throws Exception { // Arrange when(multipartFile.getOriginalFilename()).thenReturn("test.jpg"); when(multipartFile.getBytes()).thenReturn("test content".getBytes()); when(cloudinary.uploader()).thenReturn(uploader); when(uploader.upload(any(File.class), anyMap())).thenThrow(IOException.class); // Act & Assert ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { bookService.addBook("Test Book", multipartFile); }); assertEquals(HttpStatus.BAD_GATEWAY, exception.getStatusCode()); assertEquals("Failed to upload the file.", exception.getReason()); } } }
package cloudinary.upload.imageUpload.controllers; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.server.ResponseStatusException; import cloudinary.upload.imageUpload.configs.GlobalExceptionHandler; import cloudinary.upload.imageUpload.entities.Book; import cloudinary.upload.imageUpload.services.BookService; @ExtendWith(MockitoExtension.class) public class BookControllerTest { @Mock private BookService bookService; @InjectMocks private BookController bookController; private MockMvc mockMvc; @Nested class AddBook { @Test void shouldReturnSuccess() throws Exception { // Arrange MockMultipartFile image = new MockMultipartFile("imgUrl", "test.jpg", MediaType.IMAGE_JPEG_VALUE, "test content".getBytes()); Book book = new Book(); book.setName("Test Book"); book.setImgUrl("http://example.com/image.jpg"); when(bookService.addBook(any(String.class), any(MockMultipartFile.class))).thenReturn(book); mockMvc = MockMvcBuilders.standaloneSetup(bookController).build(); // Act & Assert mockMvc.perform(multipart("/addBook") .file(image) .param("name", "Test Book")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("Test Book")) .andExpect(jsonPath("$.imgUrl").value("http://example.com/image.jpg")); } @Test void shouldFailToUploadImage() throws Exception { // Arrange MockMultipartFile image = new MockMultipartFile("imgUrl", "test.jpg", MediaType.IMAGE_JPEG_VALUE, "test content".getBytes()); when(bookService.addBook(any(String.class), any(MockMultipartFile.class))) .thenThrow(new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to upload the file.")); mockMvc = MockMvcBuilders.standaloneSetup(bookController).setControllerAdvice(new GlobalExceptionHandler()) .build(); // Act & Assert mockMvc.perform(multipart("/addBook") .file(image) .param("name", "Test Book")) .andExpect(status().isInternalServerError()) .andExpect(result -> result.getResponse().equals("Failed to upload the file.")); } @Test void shouldFailWithMissingNameParameter() throws Exception { // Arrange MockMultipartFile image = new MockMultipartFile("imgUrl", "test.jpg", MediaType.IMAGE_JPEG_VALUE, "test content".getBytes()); mockMvc = MockMvcBuilders.standaloneSetup(bookController).build(); // Act & Assert mockMvc.perform(multipart("/addBook") .file(image)) .andExpect(status().isBadRequest()); } @Test void shouldFailWithMissingImageParameter() throws Exception { // Arrange mockMvc = MockMvcBuilders.standaloneSetup(bookController).build(); // Act & Assert mockMvc.perform(multipart("/addBook") .param("name", "Test Book")) .andExpect(status().isBadRequest()); } } }
Dies sind einige einfache Testfälle, mit denen Sie mit dem Testen Ihrer App beginnen können. Denken Sie daran, dass wir diese Tests umgestalten können, indem wir einige Fabriken hinzufügen, um Wiederholungen zu vermeiden.
Vielen Dank fürs Lesen.
JUnit5 – Dokumente
Mockito – Dokumente
Das obige ist der detaillierte Inhalt vonUnit-Test der Image Uploader API mit JUnitnd Mockito. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!