Spring Boot-Integrationstest mit @MockMvc, der einen leeren Körper zurückgibtJava

Java-Forum
Guest
 Spring Boot-Integrationstest mit @MockMvc, der einen leeren Körper zurückgibt

Post by Guest »

Ich habe ein Problem mit meinem Spring Boot-Integrationstest mit @MockMvc. Wenn ich den Test ausführe, schlagen die jsonPath-Behauptungen fehl, weil der Antworttext ($) nichts enthält.

Code: Select all

package env.starwars.web;

import static org.mockito.Mockito.when;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import com.fasterxml.jackson.databind.ObjectMapper;

import env.starwars.domain.Planet;
import env.starwars.domain.PlanetService;
import env.starwars.factory.PlanetFactory;

@WebMvcTest()
@AutoConfigureMockMvc
public class PlanetControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockitoBean
private PlanetService planetService;

@Test
public void createPlanet_WithValidData_ReturnCreated() throws Exception {
Planet planet = PlanetFactory.create();
when(planetService.create(planet)).thenReturn(planet);

mockMvc.perform(MockMvcRequestBuilders.post("/planets")
.content(objectMapper.writeValueAsString(planet)).contentType(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isCreated())
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value(planet.getName()))
.andExpect(MockMvcResultMatchers.jsonPath("$.terrain").value(planet.getTerrain()))
.andExpect(MockMvcResultMatchers.jsonPath("$.climate").value(planet.getClimate()));
}
}
Meine PlanetFactory:

Code: Select all

package env.starwars.factory;

import env.starwars.domain.Planet;
import env.starwars.web.dto.PlanetDto;

public class PlanetFactory {

public static Planet create() {
return new Planet("name", "climate", "terrain");
}

public static Planet createWithInvalidData() {
return new Planet("", "", "");
}

public static PlanetDto createDto() {
return new PlanetDto(1L, "name", "climate", "terrain");
}

public static PlanetDto createAalothDto() {
return new PlanetDto(1L, "Aaloth", "Unknown", "Terrestrial");
}

public static Planet createAaloth() {
return new Planet(1L, "Aaloth", "Unknown", "Terrestrial");
}
}
Hier ist ein Beispiel der Debug-Konsolenausgabe:

Code: Select all

19:04:00.130 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [env.starwars.web.PlanetControllerTest]: PlanetControllerTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
19:04:00.247 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration env.starwars.StarWarsApplication for test class env.starwars.web.PlanetControllerTest
19:04:00.300 [main] INFO org.springframework.boot.devtools.restart.RestartApplicationListener -- Restart disabled due to context in which it is running

.    ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/

:: Spring Boot ::                (v3.4.1)

2025-01-12T19:04:00.557-03:00  INFO 177734 --- [           main] env.starwars.web.PlanetControllerTest    : Starting PlanetControllerTest using Java 17.0.13 with PID 177734 (started by fynko in /home/fynko/codes/star-wars)
2025-01-12T19:04:00.558-03:00  INFO 177734 --- [           main] env.starwars.web.PlanetControllerTest    : No active profile set, falling back to 1 default profile: "default"
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-01-12T19:04:02.060-03:00  INFO 177734 --- [           main] o.s.t.web.servlet.TestDispatcherServlet  : Initializing Servlet ''
2025-01-12T19:04:02.063-03:00  INFO 177734 --- [           main] o.s.t.web.servlet.TestDispatcherServlet  : Completed initialization in 1 ms
2025-01-12T19:04:02.089-03:00  INFO 177734 --- [           main] env.starwars.web.PlanetControllerTest    : Started PlanetControllerTest in 1.792 seconds (process running for 2.431)

MockHttpServletRequest:
HTTP Method = POST
Request URI = /planets
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"65"]
Body = {"id":null,"name":"name","climate":"climate","terrain":"terrain"}
Session Attrs = {}

Handler:
Type = env.starwars.web.PlanetController
Method = env.starwars.web.PlanetController#create(Planet)
Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = null
View = null
Model = null

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 201
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []

MockHttpServletRequest:
HTTP Method = POST
Request URI = /planets
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"65"]
Body = {"id":null,"name":"name","climate":"climate","terrain":"terrain"}
Session Attrs = {}

Handler:
Type = env.starwars.web.PlanetController
Method = env.starwars.web.PlanetController#create(Planet)

Async:
Async started = false
Async result = null

Resolved Exception:
Type = null

ModelAndView:
View name = null
View = null
Model = null

FlashMap:
Attributes = null

MockHttpServletResponse:
Status = 201
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Mein Controller:

Code: Select all

package env.starwars.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import env.starwars.domain.Planet;
import env.starwars.domain.PlanetService;
import env.starwars.web.dto.PlanetDto;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@RestController
@RequestMapping("/planets")
public class PlanetController {

@Autowired
private PlanetService planetService;

@PostMapping()
public ResponseEntity
  create(@RequestBody Planet planet) {
Planet planetCreated = planetService.create(planet);

return ResponseEntity.status(HttpStatus.CREATED).body(planetCreated);
}

@GetMapping("/{id}")
public ResponseEntity getPlanetById(@PathVariable(name = "id") Long id) {
return planetService.getById(id).map(planet -> ResponseEntity.ok(planet))
.orElseGet(() -> ResponseEntity.notFound().build());
}

@GetMapping("/name/{name}")
public ResponseEntity getPlanetByName(@PathVariable(name = "name") String name) {
return planetService.getByName(name).map(planet -> ResponseEntity.ok(planet))
.orElseGet(() -> ResponseEntity.notFound().build());
}

@GetMapping
public ResponseEntity listPlanets(@RequestParam(required = false) String terrain,
@RequestParam(required = false) String climate) {
List planets = planetService.listPlanets(terrain, climate);
return ResponseEntity.ok().body(planets);
}

@DeleteMapping("/{id}")
public ResponseEntity deletePlanetById(@PathVariable(name = "id") Long id) {
planetService.deleteById(id);
return ResponseEntity.noContent().build();
}
}
Mein Service:

Code: Select all

package env.starwars.domain;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import env.starwars.utils.MapperPlanet;
import env.starwars.web.dto.PlanetDto;

@Service
public class PlanetService {

private final PlanetRepository planetRepository;
private final MapperPlanet mapperPlanet;

public PlanetService(PlanetRepository planetRepository, MapperPlanet mapperPlanet) {
this.planetRepository = planetRepository;
this.mapperPlanet = mapperPlanet;
}

public Planet create(Planet planet) {
return planetRepository.save(planet);
}

public Optional
 getById(Long id) {
Optional planet = planetRepository.findById(id);

if (planet.isPresent()) {
PlanetDto planetDto = mapperPlanet.toPlanetDto(planet.get());
return Optional.of(planetDto);
}

return Optional.empty();
}

public Optional getByName(String name) {
Optional planet = planetRepository.findByName(name);

if (planet.isPresent()) {
PlanetDto planetDto = mapperPlanet.toPlanetDto(planet.get());
return Optional.of(planetDto);
}

return Optional.empty();
}

public List listPlanets(String terrain, String climate) {
Example query = QueryBuilder.makeQuery(new Planet(climate, terrain));

return planetRepository.findAll(query).stream().map(mapperPlanet::toPlanetDto)
.collect(Collectors.toList());
}

public void deleteById(Long id) {
planetRepository.deleteById(id);
}
}
Image
Kann mir jemand helfen?
Ich würde mich wirklich über jede Hilfe freuen, die mir hilft, zu verstehen, warum der Antworttext in meinem Integrationstest leer ist.
Vielen Dank im Voraus!

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post