add controllers. add integration test for freight controller.
numerous changes to services, including using Jspecify
This commit is contained in:
@@ -18,10 +18,15 @@ dependencies {
|
||||
implementation(libs.spring.boot.starter.hateoas)
|
||||
developmentOnly(libs.spring.boot.devtools)
|
||||
|
||||
// xml
|
||||
implementation(libs.jackson.dataformat.xml)
|
||||
|
||||
// testing
|
||||
testImplementation(platform(libs.junit.bom))
|
||||
testImplementation(libs.junit.jupiter)
|
||||
testRuntimeOnly(libs.junit.platform.launcher)
|
||||
|
||||
implementation(libs.jspecify)
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[versions]
|
||||
junit = "6.0.1"
|
||||
spring-boot-plugin = "4.0.0"
|
||||
jspecify = "1.0.0"
|
||||
|
||||
[plugins]
|
||||
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot-plugin" }
|
||||
@@ -12,7 +13,12 @@ spring-boot-starter-web-test = { group = "org.springframework.boot", name = "spr
|
||||
spring-boot-starter-hateoas = { group = "org.springframework.boot", name = "spring-boot-starter-hateoas" }
|
||||
spring-boot-devtools = { group = "org.springframework.boot", name = "spring-boot-devtools" }
|
||||
|
||||
# xml
|
||||
jackson-dataformat-xml = { group = "tools.jackson.dataformat", name = "jackson-dataformat-xml" }
|
||||
|
||||
# testing
|
||||
junit-bom = { group = "org.junit", name = "junit-bom", version.ref = "junit" }
|
||||
junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter" }
|
||||
junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher" }
|
||||
|
||||
jspecify = { group = "org.jspecify", name = "jspecify", version.ref = "jspecify" }
|
||||
@@ -1,15 +1,21 @@
|
||||
package ua.com.dxrkness.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
import ua.com.dxrkness.service.FreightService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/freight")
|
||||
@RequestMapping(
|
||||
value = "/freights",
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
|
||||
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
|
||||
)
|
||||
@NullMarked
|
||||
public class FreightController {
|
||||
private final FreightService service;
|
||||
|
||||
@@ -17,8 +23,28 @@ public class FreightController {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@GetMapping(consumes = MediaType.ALL_VALUE)
|
||||
public List<Freight> getAll() {
|
||||
return service.getAll();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Freight> getById(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.getById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Freight> add(@RequestBody Freight newFreight) {
|
||||
return ResponseEntity.ok(service.add(newFreight));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<Freight> update(@PathVariable("id") long id, @RequestBody Freight newFreight) {
|
||||
return ResponseEntity.ok(service.update(id, newFreight));
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Freight> delete(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.delete(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package ua.com.dxrkness.controller;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
import ua.com.dxrkness.model.Route;
|
||||
import ua.com.dxrkness.model.Vehicle;
|
||||
import ua.com.dxrkness.repository.FreightRepository;
|
||||
import ua.com.dxrkness.repository.RouteRepository;
|
||||
import ua.com.dxrkness.repository.VehicleRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/populate")
|
||||
@NullMarked
|
||||
public class PopulateController {
|
||||
private final FreightRepository freightRepository;
|
||||
private final RouteRepository routeRepository;
|
||||
private final VehicleRepository vehicleRepository;
|
||||
|
||||
public PopulateController(FreightRepository freightRepository, RouteRepository routeRepository, VehicleRepository vehicleRepository) {
|
||||
this.freightRepository = freightRepository;
|
||||
this.routeRepository = routeRepository;
|
||||
this.vehicleRepository = vehicleRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<String> populate(@RequestParam("vals") int vals) {
|
||||
var allFreights = new ArrayList<Freight>(vals);
|
||||
for (int i = 0; i < vals; i++) {
|
||||
var f = new Freight(i);
|
||||
allFreights.add(f);
|
||||
freightRepository.add(f);
|
||||
}
|
||||
|
||||
var allVehicles = new ArrayList<Vehicle>(vals);
|
||||
for (int i = 0; i < vals; i++) {
|
||||
var v = new Vehicle(i);
|
||||
allVehicles.add(v);
|
||||
vehicleRepository.add(v);
|
||||
}
|
||||
|
||||
for (int i = 0; i < vals; i++)
|
||||
routeRepository.add(new Route(i, allVehicles.get(i), List.of(allFreights.get(i))));
|
||||
|
||||
return ResponseEntity.ok("success");
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public ResponseEntity<String> delete() {
|
||||
routeRepository.deleteAll();
|
||||
freightRepository.deleteAll();
|
||||
vehicleRepository.deleteAll();
|
||||
|
||||
return ResponseEntity.ok("success");
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
package ua.com.dxrkness.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ua.com.dxrkness.model.Route;
|
||||
import ua.com.dxrkness.service.RouteService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/route")
|
||||
@RequestMapping(
|
||||
value = "/routes",
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
|
||||
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
|
||||
)
|
||||
@NullMarked
|
||||
public class RouteController {
|
||||
private final RouteService service;
|
||||
|
||||
@@ -17,8 +24,39 @@ public class RouteController {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Route> getAll() {
|
||||
@GetMapping(consumes = MediaType.ALL_VALUE)
|
||||
public List<Route> getAll(@RequestParam(name = "freightId", required = false) @Nullable Long freightId,
|
||||
@RequestParam(name = "vehicleId", required = false) @Nullable Long vehicleId) {
|
||||
if (vehicleId != null) {
|
||||
return service.getByVehicleId(vehicleId);
|
||||
}
|
||||
if (freightId != null) {
|
||||
var route = service.getByFreightId(freightId);
|
||||
if (route == null) {
|
||||
return List.of();
|
||||
}
|
||||
return List.of(route);
|
||||
}
|
||||
return service.getAll();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Route> add(@RequestBody Route newRoute) {
|
||||
return ResponseEntity.ok(service.add(newRoute));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<Route> update(@PathVariable("id") long id, @RequestBody Route newRoute) {
|
||||
return ResponseEntity.ok(service.update(id, newRoute));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Route> getById(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.getById(id));
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Route> delete(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.delete(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package ua.com.dxrkness.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ua.com.dxrkness.model.Vehicle;
|
||||
import ua.com.dxrkness.service.VehicleService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/vehicle")
|
||||
@RequestMapping(
|
||||
value = "/vehicles",
|
||||
produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
|
||||
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
|
||||
)
|
||||
@NullMarked
|
||||
public class VehicleController {
|
||||
private final VehicleService service;
|
||||
|
||||
@@ -17,8 +23,28 @@ public class VehicleController {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@GetMapping(consumes = MediaType.ALL_VALUE)
|
||||
public List<Vehicle> getAll() {
|
||||
return service.getAll();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Vehicle> getById(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.getById(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Vehicle> add(@RequestBody Vehicle newVehicle) {
|
||||
return ResponseEntity.ok(service.add(newVehicle));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<Vehicle> update(@PathVariable("id") long id, @RequestBody Vehicle newVehicle) {
|
||||
return ResponseEntity.ok(service.update(id, newVehicle));
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/{id}", consumes = MediaType.ALL_VALUE)
|
||||
public ResponseEntity<Vehicle> delete(@PathVariable("id") long id) {
|
||||
return ResponseEntity.ofNullable(service.delete(id));
|
||||
}
|
||||
}
|
||||
|
||||
4
src/main/java/ua/com/dxrkness/package-info.java
Normal file
4
src/main/java/ua/com/dxrkness/package-info.java
Normal file
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package ua.com.dxrkness;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -1,10 +1,10 @@
|
||||
package ua.com.dxrkness.repository;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import ua.com.dxrkness.model.Identifiable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
abstract class CrudRepository<T extends Identifiable> {
|
||||
protected final List<T> STORAGE = new ArrayList<>();
|
||||
@@ -13,13 +13,20 @@ abstract class CrudRepository<T extends Identifiable> {
|
||||
return new ArrayList<>(STORAGE); // defensive copy
|
||||
}
|
||||
|
||||
public Optional<T> getById(long id) {
|
||||
return STORAGE.stream().filter(el -> el.id() == id).findFirst();
|
||||
public @Nullable T getById(long id) {
|
||||
T found = null;
|
||||
for (var el : STORAGE) {
|
||||
if (el.id() == id) {
|
||||
found = el;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public T add(T toAdd) {
|
||||
public int add(T toAdd) {
|
||||
STORAGE.add(toAdd);
|
||||
return toAdd;
|
||||
return STORAGE.size();
|
||||
}
|
||||
|
||||
public T update(long id, T newT) {
|
||||
@@ -32,14 +39,20 @@ abstract class CrudRepository<T extends Identifiable> {
|
||||
return newT;
|
||||
}
|
||||
|
||||
public Optional<T> delete(long id) {
|
||||
public @Nullable T delete(long id) {
|
||||
T deleted = null;
|
||||
for (int i = 0; i < STORAGE.size(); i++) {
|
||||
if (STORAGE.get(i).id() == id) {
|
||||
deleted = STORAGE.remove(i);
|
||||
for (var itr = STORAGE.iterator(); itr.hasNext(); ) {
|
||||
T next = itr.next();
|
||||
if (next.id() == id) {
|
||||
deleted = next;
|
||||
itr.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(deleted);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void deleteAll() {
|
||||
STORAGE.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
package ua.com.dxrkness.repository;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
|
||||
@Repository
|
||||
public final class FreightRepository extends CrudRepository<Freight> {
|
||||
@PostConstruct
|
||||
private void initData() {
|
||||
for (int i = 0; i < 100; i++)
|
||||
add(new Freight(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
package ua.com.dxrkness.repository;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
import ua.com.dxrkness.model.Route;
|
||||
import ua.com.dxrkness.model.Vehicle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public final class RouteRepository extends CrudRepository<Route> {
|
||||
@PostConstruct
|
||||
private void initData() {
|
||||
for (int i = 0; i < 100; i++)
|
||||
add(new Route(i, new Vehicle(i), List.of(new Freight(i))));
|
||||
public @Nullable Route getByFreightId(long freightId) {
|
||||
Route found = null;
|
||||
out: for (var route : STORAGE) {
|
||||
var freights = route.freights();
|
||||
for (var freight : freights) {
|
||||
if (freight.id() == freightId) {
|
||||
found = route;
|
||||
break out;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public Optional<Route> getByFreightId(long freightId) {
|
||||
return STORAGE.stream()
|
||||
.filter(route -> route.freights().stream().anyMatch(freight -> freight.id() == freightId))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
public Optional<Route> getByVehicleId(long vehicleId) {
|
||||
return STORAGE.stream()
|
||||
.filter(route -> route.vehicle().id() == vehicleId)
|
||||
.findAny();
|
||||
public List<Route> getByVehicleId(long vehicleId) {
|
||||
List<Route> found = new ArrayList<>();
|
||||
for (var route : STORAGE) {
|
||||
if (route.vehicle().id() == vehicleId) {
|
||||
found.add(route);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
package ua.com.dxrkness.repository;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ua.com.dxrkness.model.Vehicle;
|
||||
|
||||
@Repository
|
||||
public final class VehicleRepository extends CrudRepository<Vehicle> {
|
||||
@PostConstruct
|
||||
private void initData() {
|
||||
for (int i = 0; i < 100; i++)
|
||||
add(new Vehicle(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ua.com.dxrkness.service;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
import ua.com.dxrkness.repository.FreightRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public final class FreightService {
|
||||
@@ -20,18 +20,20 @@ public final class FreightService {
|
||||
}
|
||||
|
||||
public Freight add(Freight freight) {
|
||||
return repo.add(freight);
|
||||
int id = repo.add(freight);
|
||||
return new Freight(id);
|
||||
}
|
||||
|
||||
public Optional<Freight> getById(long id) {
|
||||
public @Nullable Freight getById(long id) {
|
||||
return repo.getById(id);
|
||||
}
|
||||
|
||||
public Freight update(long id, Freight newFreight) {
|
||||
newFreight = new Freight(id);
|
||||
return repo.update(id, newFreight);
|
||||
}
|
||||
|
||||
public Optional<Freight> delete(long id) {
|
||||
public @Nullable Freight delete(long id) {
|
||||
return repo.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ua.com.dxrkness.service;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ua.com.dxrkness.model.Route;
|
||||
import ua.com.dxrkness.repository.RouteRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public final class RouteService {
|
||||
@@ -19,27 +19,29 @@ public final class RouteService {
|
||||
return repo.getAll();
|
||||
}
|
||||
|
||||
public Optional<Route> getById(long id) {
|
||||
public @Nullable Route getById(long id) {
|
||||
return repo.getById(id);
|
||||
}
|
||||
|
||||
public Route add(Route route) {
|
||||
return repo.add(route);
|
||||
int id = repo.add(route);
|
||||
return new Route(id, route.vehicle(), route.freights());
|
||||
}
|
||||
|
||||
public Optional<Route> getByFreightId(long freightId) {
|
||||
public @Nullable Route getByFreightId(long freightId) {
|
||||
return repo.getByFreightId(freightId);
|
||||
}
|
||||
|
||||
public Optional<Route> getByVehicleId(long vehicleId) {
|
||||
public List<Route> getByVehicleId(long vehicleId) {
|
||||
return repo.getByVehicleId(vehicleId);
|
||||
}
|
||||
|
||||
public Route update(long id, Route newRoute) {
|
||||
newRoute = new Route(id, newRoute.vehicle(), newRoute.freights());
|
||||
return repo.update(id, newRoute);
|
||||
}
|
||||
|
||||
public Optional<Route> delete(long id) {
|
||||
public @Nullable Route delete(long id) {
|
||||
return repo.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ua.com.dxrkness.service;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ua.com.dxrkness.model.Vehicle;
|
||||
import ua.com.dxrkness.repository.VehicleRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public final class VehicleService {
|
||||
@@ -20,18 +20,20 @@ public final class VehicleService {
|
||||
}
|
||||
|
||||
public Vehicle add(Vehicle veh) {
|
||||
return repo.add(veh);
|
||||
int id = repo.add(veh);
|
||||
return new Vehicle(id);
|
||||
}
|
||||
|
||||
public Optional<Vehicle> getById(long id) {
|
||||
public @Nullable Vehicle getById(long id) {
|
||||
return repo.getById(id);
|
||||
}
|
||||
|
||||
public Vehicle update(long id, Vehicle newVehicle) {
|
||||
newVehicle = new Vehicle(id);
|
||||
return repo.update(id, newVehicle);
|
||||
}
|
||||
|
||||
public Optional<Vehicle> delete(long id) {
|
||||
public @Nullable Vehicle delete(long id) {
|
||||
return repo.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
package ua.com.dxrkness.integration;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import ua.com.dxrkness.model.Freight;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@SpringBootTest
|
||||
@NullMarked
|
||||
class FreightIntegrationTest {
|
||||
private RestTestClient testClient;
|
||||
private RestTestClient populateClient;
|
||||
private static final int AMOUNT = 100;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(WebApplicationContext context) {
|
||||
populateClient = RestTestClient.bindToApplicationContext(context).baseUrl("/populate").build();
|
||||
populateClient.get().uri("?vals=%d".formatted(AMOUNT)).exchange();
|
||||
testClient = RestTestClient.bindToApplicationContext(context).baseUrl("/freights").build();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void teardown() {
|
||||
populateClient.delete().exchange();
|
||||
}
|
||||
|
||||
private static Stream<MediaType> mediaTypesClientConsumes() {
|
||||
return Stream.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> mediaTypesClientConsumesProduces() {
|
||||
return Stream.of(
|
||||
Arguments.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON),
|
||||
Arguments.of(MediaType.APPLICATION_XML, MediaType.APPLICATION_XML),
|
||||
Arguments.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML),
|
||||
Arguments.of(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumes")
|
||||
void getAll(MediaType mediaType) {
|
||||
// given
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.get()
|
||||
.accept(mediaType)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(new ParameterizedTypeReference<List<Freight>>() {
|
||||
})
|
||||
.consumeWith(res -> then(res.getResponseBody()).hasSizeGreaterThan(0));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumes")
|
||||
void getByIdReturnsEntity(MediaType mediaType) {
|
||||
// given
|
||||
final var id = 1;
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.get().uri("/{id}", id)
|
||||
.accept(mediaType)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Freight.class)
|
||||
.isEqualTo(new Freight(1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumes")
|
||||
void getByIdReturnsNotFound(MediaType mediaType) {
|
||||
// given
|
||||
final var id = -1;
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.get().uri("/{id}", id)
|
||||
.accept(mediaType)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isNotFound();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumesProduces")
|
||||
void add(MediaType clientConsumes, MediaType clientProduces) {
|
||||
// given
|
||||
final var newEntity = new Freight(444);
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.post()
|
||||
.accept(clientConsumes)
|
||||
.contentType(clientProduces)
|
||||
.body(newEntity)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Freight.class)
|
||||
.isEqualTo(new Freight(AMOUNT + 1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumesProduces")
|
||||
void update(MediaType clientConsumes, MediaType clientProduces) {
|
||||
// given
|
||||
final var existingEntityId = AMOUNT-1;
|
||||
final var newEntity = new Freight(432);
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.put().uri("/{id}", existingEntityId)
|
||||
.accept(clientConsumes)
|
||||
.contentType(clientProduces)
|
||||
.body(newEntity)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(Freight.class)
|
||||
.value(val -> {
|
||||
then(val).isNotNull();
|
||||
then(val.id()).isEqualTo(existingEntityId);
|
||||
then(val).usingRecursiveComparison()
|
||||
.ignoringFields("id")
|
||||
.isEqualTo(newEntity);
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("mediaTypesClientConsumes")
|
||||
void delete(MediaType mediaType) {
|
||||
// given
|
||||
final var existingEntityId = AMOUNT-1;
|
||||
|
||||
// when
|
||||
// then
|
||||
testClient.delete().uri("/{id}", existingEntityId)
|
||||
.accept(mediaType)
|
||||
.exchange()
|
||||
.expectBody(Freight.class)
|
||||
.value(val -> {
|
||||
then(val).isNotNull();
|
||||
then(val.id()).isEqualTo(existingEntityId);
|
||||
});
|
||||
|
||||
testClient.get().uri("/{id}", existingEntityId)
|
||||
.accept(mediaType)
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isNotFound();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user