Dalam artikel pertama siri ini, kami telah membina pemuat naik imej yang mantap menggunakan Spring Boot, Cloudinary, Docker dan PostgreSQL. Kami meliputi segala-galanya daripada menyediakan projek kepada membuat permintaan kepada titik akhir yang menyimpan imej dan maklumat. Jika anda belum membaca artikel itu lagi, saya amat mengesyorkan bermula di sana untuk mendapatkan asas aplikasi yang kukuh yang akan kami usahakan.
Kini, tiba masanya untuk memastikan aplikasi kami boleh dipercayai dan mengekalkan integritinya dari semasa ke semasa. Ini membawa kita kepada aspek penting pembangunan perisian: pengujian. Dalam artikel ini, kami akan menumpukan pada menulis ujian unit untuk API pemuat naik imej kami. Kami akan meneroka cara untuk mengejek kebergantungan dan menulis ujian yang merangkumi bahagian perkhidmatan kami yang berlainan.
Ujian unit bukan sahaja membantu menangkap pepijat lebih awal tetapi juga memastikan kod kami boleh diselenggara dan berskala. Pada penghujung artikel ini, anda akan mempunyai set ujian komprehensif untuk API pemuat naik imej anda, memberikan anda keyakinan bahawa aplikasi anda berfungsi seperti yang diharapkan.
Mari kita terjun ke dunia ujian unit dan jadikan API pemuat naik imej kami kalis peluru!
Saya menggunakan VSCode dengan Pek Sambungan untuk Java. Kini kami bersedia untuk menulis ujian kami.
Jika anda menggunakan IDE lain, lihat sokongan untuk kesemuanya di sini dalam dokumentasi JUnit5.
Klik kanan pada kelas BookService, klik pada Pergi ke Ujian, dan pilih kaedah yang anda mahu hasilkan ujian daripada menu.
Fail yang serupa, seperti di bawah, akan dijana:
import org.junit.jupiter.api.Test; public class BookServiceTest { @Test void testAddBook() { } }
Ingat, untuk artikel ini, kami akan menggunakan corak AAA ujian (Susun - Bertindak - Tegas).
@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()); } } }
Ini ialah beberapa kes ujian mudah untuk anda mula menguji apl anda. Ingat, kita boleh memfaktorkan semula ujian ini dengan menambahkan beberapa kilang untuk mengelakkan pengulangan.
Terima kasih kerana membaca.
JUnit5 - Dokumen
Mockito - Dokumen
Atas ialah kandungan terperinci Unit Menguji API Pemuat Naik Imej dengan JUnitnd Mockito. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!