Test endpointu z plikiem MultipartFile

0

Mam metodę w kontrolerze, która odbiera nowe dane do aktualizacji profilu użytkownika. W parametrze tej metody jest dto, który ma np. imię, nazwisko i zdjęcie profilowe, czyli MultipartFile.

@PatchMapping("/settings/profile")
@ResponseStatus(HttpStatus.NO_CONTENT)
void updateUserProfile(@Valid @RequestBody AppUserProfileEditDTO userProfile) {
    appUserService.updateUserProfile(currentUserFacade.getCurrentUser(), userProfile);
}

Napisałem sobie taki test jak na screenie, w sekcji given robię zapis użytkownika do bazy danych i tworzę ten dto z nowymi danymi. Linia 281 wyrzuca wyjątek InvalidDefinitionException.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: pl.secret.iteventsapi.appuser.domain.dto.AppUserProfileEditDTO["profileImage"]->org.springframework.mock.web.MockMultipartFile["inputStream"])
@Test
@Transactional
@WithMockUser(username = "[email protected]")
void shouldReturnUpdatedUserProfile() throws Exception {
    // given
    AppUser user = AppUserCreator.create("Jan", "Kowalski", imageRepository.save(ProfileImageCreator.createDefaultProfileImage()));
    appUserRepository.save(user);
    AppUserProfileEditDTO newUserProfileData = AppUserProfileEditDTOCreator.create(
            user,
            "Kraków",
            "Cześć!");
    // when
    MockHttpServletRequestBuilder request = MockMvcRequestBuilders
            .patch("/api/v1/settings/profile")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(newUserProfileData));
    mockMvc.perform(request)
            .andDo(print())
            .andExpect(status().isNoContent());
    // then
    AppUser userAfterUpdate = appUserRepository.findById(user.getId()).get();
    assertThat(userAfterUpdate.getCity()).isEqualTo(newUserProfileData.getCity());
    assertThat(userAfterUpdate.getBio()).isEqualTo(newUserProfileData.getBio());
}

Wiem, że tutaj jest problem z serializacją pliku. Jak powinno się tworzyć takie dto w testach i jak napisać test dla takiej metody

0

Ciekawe jestem tego kodu, bo obawiam się, że zapis do DB dzieje się w kontrolerze

0

Jak w kontrolerze? AppUserService to serwis a nie repozytorium i dopiero w metodzie serwisowej robiony jest zapis do bazy danych.

0

Dobe testy wyglądałyby jakoś tak:

@Test
void shouldUpdateUserProfile() {
    // given
    var logged = user("Jan", "Kowalski", defaultImage());
    // when
    var response = request("/api/v1/settings/profile", profileEdit(logged, "Kraków", "Cześć"));
    // then
    assertResponseStatus(response, status().isNoContent());
}

@Test
void shouldGetUpdatedUserProfile() {
    // given
    var logged = user("Jan", "Kowalski", defaultImage());
    // when
    var response = request("/api/v1/settings/profile", profileEdit(logged, "Kraków", "Cześć"));
    // then
    var userData = userData("Jan", "Kowalski");
    assertEquals("Kraków", userData.getCity());
    assertEquals("Cześć!", userData.getBio());
}
0

JSON to nie multipart. Serializer się wywala, bo masz dane binarne, które bez specjalne konwersji nie wciśnie się do JSONa.

Do multipartów masz osobną metodę https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.html#multipart(java.lang.String,java.lang.Object...)

0

@Riddle rozumiem, że chodzi Ci o podzielenie tego testu na dwa osobne, pierwszy sprawdzi tylko czy aktualizacja wykonała się poprawnie poprzez sprawdzenie kodu odpowiedzi, a drugi pobierze tego użytkownika z bazy i sprawdzi zaktualizowane pola. Ok, dzięki za radę.

@szatkus1 znam tą metodę, ale nią można przetestować chyba tylko taki endpoint gdzie jest sam plik. A co do tej konwersji, masz na myśli przepuszczenie pliku przez Base64 i wysłanie jako Stringa?

0
Scarilt napisał(a):

@Riddle rozumiem, że chodzi Ci o podzielenie tego testu na dwa osobne, pierwszy sprawdzi tylko czy aktualizacja wykonała się poprawnie poprzez sprawdzenie kodu odpowiedzi, a drugi pobierze tego użytkownika z bazy i sprawdzi zaktualizowane pola. Ok, dzięki za radę.

Tak, oraz to żeby schować szczegóły testu, i uwidocznić rzeczy istotne.

0

oraz to żeby schować szczegóły testu, i uwidocznić rzeczy istotne.

Masz na myśli zapis użytkownika do bazy danych i tworzenie tego DTO z nowymi danymi?

1 użytkowników online, w tym zalogowanych: 0, gości: 1