Rumah  >  Artikel  >  Java  >  Unit Menguji API Pemuat Naik Imej dengan JUnitnd Mockito

Unit Menguji API Pemuat Naik Imej dengan JUnitnd Mockito

WBOY
WBOYasal
2024-08-08 09:19:01777semak imbas

Unit Testing the Image Uploader API with JUnitnd Mockito

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!

Sediakan

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.

Ujian

1. Ujian Perkhidmatan Buku

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).

1.1. Sifat mengejek

@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;

}
  • Anotasi @Mock mengejek/mensimulasikan gelagat sifat atau kebergantungan yang akan digunakan oleh kelas.
  • Anotasi @InjectMocks mencipta dan menyuntik olok-olok ke dalam medan yang sepadan.

1.2. Ujian menulis

  • Menguji kes kejayaan (harusCreateANewBook).
  • Menguji panggilan ke repositori (shouldCallRepositorySave).
  • Menguji jika muat naik gagal (sepatutnyaFailTheUpload).
@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());
        }
    }
}

2. Ujian Pengawal Buku

  • Menguji kes kejayaan (shouldReturnSuccess)
  • Menguji kes gagal (sepatutnyaFailToUploadImage)
  • Ujian dengan parameter nama yang tiada (sepatutnyaFailWithMissingNameParameter)
  • Ujian dengan parameter imgUrl yang tiada (sepatutnyaFailWithMissingImageParameter)
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());
        }
    }

}

Kesimpulan

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.

Rujukan

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!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Amalan Terbaik Sirialisasi JavaArtikel seterusnya:Amalan Terbaik Sirialisasi Java