Heim  >  Artikel  >  Java  >  Unit-Test der Image Uploader API mit JUnitnd Mockito

Unit-Test der Image Uploader API mit JUnitnd Mockito

WBOY
WBOYOriginal
2024-08-08 09:19:01732Durchsuche

Unit Testing the Image Uploader API with JUnitnd Mockito

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!

Einrichten

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.

Tests

1. Servicetests buchen

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.

1.1. Spotteigenschaften

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

}
  • Die @Mock-Annotationen verspotten/simulieren das Verhalten von Eigenschaften oder Abhängigkeiten, die von der Klasse verwendet werden.
  • Die Annotation @InjectMocks erstellt die Mocks und fügt sie in die entsprechenden Felder ein.

1.2. Schreibtests

  • Testen eines Erfolgsfalls (sollte ein neues Buch erstellen).
  • Testen eines Aufrufs an das Repository (shouldCallRepositorySave).
  • Testen, ob der Upload fehlschlägt (shouldFailTheUpload).
@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. Buchen Sie Controller-Tests

  • Testen eines Erfolgsfalls (shouldReturnSuccess)
  • Testen eines Fehlerfalls (shouldFailToUploadImage)
  • Testen mit einem fehlenden Namensparameter (shouldFailWithMissingNameParameter)
  • Testen mit einem fehlenden imgUrl-Parameter (shouldFailWithMissingImageParameter)
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());
        }
    }

}

Abschluss

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.

Referenz

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn