diff --git a/.woodpecker/maven.yaml b/.woodpecker/maven.yaml index 6458761..82461b2 100644 --- a/.woodpecker/maven.yaml +++ b/.woodpecker/maven.yaml @@ -1,5 +1,5 @@ variables: - &maven_image maven:3.9.6-eclipse-temurin-21-alpine + &maven_image maven:3.9.6-eclipse-temurin-17-alpine steps: - name: build diff --git a/pom.xml b/pom.xml index 9ae7829..3756469 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ ${source.encoding} - 21 + 17 ${java.version} ${java.version} @@ -51,10 +51,6 @@ org.springframework.boot spring-boot-starter-data-jpa - - org.springframework.boot - spring-boot-starter-actuator - @@ -73,12 +69,6 @@ org.springframework.boot spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-webflux - test org.junit.jupiter @@ -119,32 +109,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - - - default-test - - - **/*Tests.java - - - - - integration-tests - test - - test - - - - **/*Test.java - - - - - diff --git a/src/main/java/eu/ztsh/wymiana/config/NbpProperties.java b/src/main/java/eu/ztsh/wymiana/config/NbpProperties.java deleted file mode 100644 index 0ed6c42..0000000 --- a/src/main/java/eu/ztsh/wymiana/config/NbpProperties.java +++ /dev/null @@ -1,8 +0,0 @@ -package eu.ztsh.wymiana.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("nbp") -public record NbpProperties(String baseurl) { - -} diff --git a/src/main/java/eu/ztsh/wymiana/config/RestClientConfiguration.java b/src/main/java/eu/ztsh/wymiana/config/RestClientConfiguration.java index f264dbe..74ee47b 100644 --- a/src/main/java/eu/ztsh/wymiana/config/RestClientConfiguration.java +++ b/src/main/java/eu/ztsh/wymiana/config/RestClientConfiguration.java @@ -8,9 +8,9 @@ import org.springframework.web.client.RestClient; public class RestClientConfiguration { @Bean - public RestClient restClient(NbpProperties nbpProperties) { + public RestClient restClient() { return RestClient.builder() - .baseUrl(nbpProperties.baseurl()) + .baseUrl("http://api.nbp.pl") .defaultHeader("Accept", "application/json") .build(); } diff --git a/src/main/java/eu/ztsh/wymiana/exception/UserNotFoundException.java b/src/main/java/eu/ztsh/wymiana/exception/UserNotFoundException.java deleted file mode 100644 index 7390eb3..0000000 --- a/src/main/java/eu/ztsh/wymiana/exception/UserNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package eu.ztsh.wymiana.exception; - -import eu.ztsh.wymiana.web.model.CurrencyExchangeRequest; - -public class UserNotFoundException extends RuntimeException { - - public UserNotFoundException(CurrencyExchangeRequest entity) { - super("User with PESEL %s not found".formatted(entity.pesel())); - } - -} diff --git a/src/main/java/eu/ztsh/wymiana/service/CurrencyService.java b/src/main/java/eu/ztsh/wymiana/service/CurrencyService.java index 401626a..b00f761 100644 --- a/src/main/java/eu/ztsh/wymiana/service/CurrencyService.java +++ b/src/main/java/eu/ztsh/wymiana/service/CurrencyService.java @@ -2,7 +2,6 @@ package eu.ztsh.wymiana.service; import eu.ztsh.wymiana.exception.ExchangeFailedException; import eu.ztsh.wymiana.exception.InsufficientFundsException; -import eu.ztsh.wymiana.exception.UserNotFoundException; import eu.ztsh.wymiana.model.Currency; import eu.ztsh.wymiana.model.User; import eu.ztsh.wymiana.validation.InstanceValidator; @@ -50,7 +49,7 @@ public class CurrencyService { user.currencies().putAll(exchanged); return userService.update(user); }) - .orElseThrow(() -> new UserNotFoundException(request)); + .orElseThrow(ExchangeFailedException::new); } private Currency create(String symbol) { diff --git a/src/main/java/eu/ztsh/wymiana/service/UserService.java b/src/main/java/eu/ztsh/wymiana/service/UserService.java index 857bc0f..f9e7cde 100644 --- a/src/main/java/eu/ztsh/wymiana/service/UserService.java +++ b/src/main/java/eu/ztsh/wymiana/service/UserService.java @@ -7,13 +7,10 @@ import eu.ztsh.wymiana.util.UserMapper; import eu.ztsh.wymiana.validation.InstanceValidator; import eu.ztsh.wymiana.web.model.UserCreateRequest; import lombok.RequiredArgsConstructor; -import org.hibernate.validator.constraints.pl.PESEL; import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; import java.util.Optional; -@Validated @RequiredArgsConstructor @Service public class UserService { @@ -29,7 +26,7 @@ public class UserService { return UserMapper.entityToPojo(userRepository.save(UserMapper.requestToEntity(request))); } - public Optional get(@PESEL String pesel) { + public Optional get(String pesel) { return userRepository.findById(pesel).map(UserMapper::entityToPojo); } diff --git a/src/main/java/eu/ztsh/wymiana/web/controller/ExchangeController.java b/src/main/java/eu/ztsh/wymiana/web/controller/ExchangeController.java deleted file mode 100644 index ae666ef..0000000 --- a/src/main/java/eu/ztsh/wymiana/web/controller/ExchangeController.java +++ /dev/null @@ -1,42 +0,0 @@ -package eu.ztsh.wymiana.web.controller; - -import eu.ztsh.wymiana.exception.InsufficientFundsException; -import eu.ztsh.wymiana.exception.UserAlreadyExistsException; -import eu.ztsh.wymiana.exception.UserNotFoundException; -import eu.ztsh.wymiana.service.CurrencyService; -import eu.ztsh.wymiana.validation.ValidationFailedException; -import eu.ztsh.wymiana.web.model.CurrencyExchangeRequest; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RequiredArgsConstructor -@Validated -@RestController -@RequestMapping(path = "/api/exchange", produces = "application/json") -public class ExchangeController { - - private final CurrencyService currencyService; - - @PostMapping - public ResponseEntity exchange(@Valid @RequestBody CurrencyExchangeRequest request) { - try { - return ResponseEntity.status(200).body(currencyService.exchange(request)); - } catch (Exception e) { - var status = switch (e) { - case InsufficientFundsException ignored -> HttpStatus.BAD_REQUEST; - case UserNotFoundException ignored -> HttpStatus.NOT_FOUND; - default -> HttpStatus.INTERNAL_SERVER_ERROR; - }; - return ResponseEntity.status(status).body(e.getMessage()); - } - } - -} diff --git a/src/main/java/eu/ztsh/wymiana/web/controller/UserController.java b/src/main/java/eu/ztsh/wymiana/web/controller/UserController.java deleted file mode 100644 index 319d93a..0000000 --- a/src/main/java/eu/ztsh/wymiana/web/controller/UserController.java +++ /dev/null @@ -1,55 +0,0 @@ -package eu.ztsh.wymiana.web.controller; - -import eu.ztsh.wymiana.exception.UserAlreadyExistsException; -import eu.ztsh.wymiana.model.User; -import eu.ztsh.wymiana.service.UserService; -import eu.ztsh.wymiana.validation.ValidationFailedException; -import eu.ztsh.wymiana.web.model.UserCreateRequest; -import jakarta.validation.Valid; -import jakarta.validation.ValidationException; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RequiredArgsConstructor -@Validated -@RestController -@RequestMapping(path = "/api/user", produces = "application/json") -public class UserController { - - private final UserService userService; - - @GetMapping("{pesel}") - public ResponseEntity get(@PathVariable("pesel") String pesel) { - try { - return userService.get(pesel) - .map(ResponseEntity::ok) - .orElse(ResponseEntity.notFound().build()); - } catch (ValidationException e) { - return ResponseEntity.badRequest().build(); - } - } - - @PostMapping - public ResponseEntity create(@Valid @RequestBody UserCreateRequest request) { - try { - userService.create(request); - } catch (Exception e) { - var status = switch (e) { - case ValidationFailedException ignored -> HttpStatus.BAD_REQUEST; - case UserAlreadyExistsException ignored -> HttpStatus.CONFLICT; - default -> HttpStatus.INTERNAL_SERVER_ERROR; - }; - return ResponseEntity.status(status).body(e.getMessage()); - } - return ResponseEntity.status(204).build(); - } - -} diff --git a/src/main/java/eu/ztsh/wymiana/web/model/UserCreateRequest.java b/src/main/java/eu/ztsh/wymiana/web/model/UserCreateRequest.java index bd7b1b4..6c15a62 100644 --- a/src/main/java/eu/ztsh/wymiana/web/model/UserCreateRequest.java +++ b/src/main/java/eu/ztsh/wymiana/web/model/UserCreateRequest.java @@ -4,13 +4,12 @@ import eu.ztsh.wymiana.validation.Adult; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; import lombok.Builder; -import org.hibernate.validator.constraints.pl.PESEL; @Builder public record UserCreateRequest( @NotNull String name, @NotNull String surname, - @PESEL @Adult String pesel, + @Adult String pesel, @Min(0) double pln) { } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 47b720c..ae6306d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -2,9 +2,6 @@ hsqldb: name: db port: 9090 -nbp: - baseurl: "http://api.nbp.pl" - spring: datasource: username: sa @@ -14,12 +11,3 @@ spring: jpa: hibernate: ddl-auto: create - -management: - endpoints: - jmx: - exposure: - exclude: '*' - web: - exposure: - include: health diff --git a/src/test/java/eu/ztsh/wymiana/EntityCreator.java b/src/test/java/eu/ztsh/wymiana/EntityCreator.java index 617cbfa..c0bb186 100644 --- a/src/test/java/eu/ztsh/wymiana/EntityCreator.java +++ b/src/test/java/eu/ztsh/wymiana/EntityCreator.java @@ -2,17 +2,13 @@ package eu.ztsh.wymiana; import eu.ztsh.wymiana.data.entity.CurrencyEntity; import eu.ztsh.wymiana.data.entity.UserEntity; -import eu.ztsh.wymiana.model.Currency; import eu.ztsh.wymiana.model.Rate; import eu.ztsh.wymiana.model.Rates; -import eu.ztsh.wymiana.model.User; import eu.ztsh.wymiana.web.model.CurrencyExchangeRequest; import eu.ztsh.wymiana.web.model.UserCreateRequest; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; public class EntityCreator { @@ -20,8 +16,6 @@ public class EntityCreator { public static class Constants { public static String PESEL = "00281018264"; - public static String INVALID_PESEL = PESEL.replace('6', '7'); - public static String ANOTHER_PESEL = "08280959342"; public static String NAME = "Janina"; public static String SURNAME = "Kowalska"; public static double PLN = 20.10; @@ -34,25 +28,10 @@ public class EntityCreator { } - public static UserEntityBuilder userEntity() { + public static UserEntityBuilder user() { return new UserEntityBuilder(); } - public static User user() { - return user(Constants.PLN, 0); - } - - public static User user(double pln, double usd) { - Map currencies = new HashMap<>(); - if (pln > 0) { - currencies.put("PLN", new Currency("PLN", pln)); - } - if (usd > 0) { - currencies.put("USD", new Currency("USD", usd)); - } - return new User(Constants.NAME, Constants.SURNAME, Constants.PESEL, currencies); - } - public static UserCreateRequest.UserCreateRequestBuilder userRequest() { return UserCreateRequest.builder().name(Constants.NAME) .surname(Constants.SURNAME) diff --git a/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java b/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java index 20b7868..63cd478 100644 --- a/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java +++ b/src/test/java/eu/ztsh/wymiana/data/repository/UserRepositoryTest.java @@ -18,7 +18,7 @@ class UserRepositoryTest extends RepositoryBasedTest { @Transactional @DisplayName("Basic insert & get test") void basicTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); expect(entity); } diff --git a/src/test/java/eu/ztsh/wymiana/service/CurrencyServiceTest.java b/src/test/java/eu/ztsh/wymiana/service/CurrencyServiceTest.java index c44625e..95b1442 100644 --- a/src/test/java/eu/ztsh/wymiana/service/CurrencyServiceTest.java +++ b/src/test/java/eu/ztsh/wymiana/service/CurrencyServiceTest.java @@ -5,7 +5,6 @@ import eu.ztsh.wymiana.RepositoryBasedTest; import eu.ztsh.wymiana.data.repository.UserRepository; import eu.ztsh.wymiana.exception.ExchangeFailedException; import eu.ztsh.wymiana.exception.InsufficientFundsException; -import eu.ztsh.wymiana.exception.UserNotFoundException; import eu.ztsh.wymiana.validation.InstanceValidator; import eu.ztsh.wymiana.validation.ValidationFailedException; import jakarta.transaction.Transactional; @@ -38,7 +37,7 @@ class CurrencyServiceTest extends RepositoryBasedTest { @Transactional @Test void plnToUsdToSellSuccessTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); var result = currencyService.exchange(EntityCreator.exchangeRequest() .from(PLN_SYMBOL) @@ -47,14 +46,14 @@ class CurrencyServiceTest extends RepositoryBasedTest { .build()); assertThat(result.currencies()) .matches(map -> map.get(PLN_SYMBOL).amount() == 0 && map.get(USD_SYMBOL).amount() == USD_BUY); - var expected = EntityCreator.userEntity().pln(0).usd(USD_BUY).build(); + var expected = EntityCreator.user().pln(0).usd(USD_BUY).build(); expect(expected); } @Transactional @Test void plnToUsdToBuySuccessTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); var result = currencyService.exchange(EntityCreator.exchangeRequest() .from(PLN_SYMBOL) @@ -63,14 +62,14 @@ class CurrencyServiceTest extends RepositoryBasedTest { .build()); assertThat(result.currencies()) .matches(map -> map.get(PLN_SYMBOL).amount() == 0 && map.get(USD_SYMBOL).amount() == USD_BUY); - var expected = EntityCreator.userEntity().pln(0).usd(USD_BUY).build(); + var expected = EntityCreator.user().pln(0).usd(USD_BUY).build(); expect(expected); } @Transactional @Test void usdToPlnToSellSuccessTest() { - var entity = EntityCreator.userEntity().pln(-1).usd(USD_SELL).build(); + var entity = EntityCreator.user().pln(-1).usd(USD_SELL).build(); userRepository.save(entity); var result = currencyService.exchange(EntityCreator.exchangeRequest() .from(USD_SYMBOL) @@ -79,14 +78,14 @@ class CurrencyServiceTest extends RepositoryBasedTest { .build()); assertThat(result.currencies()) .matches(map -> map.get(PLN_SYMBOL).amount() == PLN && map.get(USD_SYMBOL).amount() == 0); - var expected = EntityCreator.userEntity().pln(PLN).usd(0).build(); + var expected = EntityCreator.user().pln(PLN).usd(0).build(); expect(expected); } @Transactional @Test void usdToPlnToBuySuccessTest() { - var entity = EntityCreator.userEntity().pln(-1).usd(USD_SELL).build(); + var entity = EntityCreator.user().pln(-1).usd(USD_SELL).build(); userRepository.save(entity); var result = currencyService.exchange(EntityCreator.exchangeRequest() .from(USD_SYMBOL) @@ -95,14 +94,14 @@ class CurrencyServiceTest extends RepositoryBasedTest { .build()); assertThat(result.currencies()) .matches(map -> map.get(PLN_SYMBOL).amount() == PLN && map.get(USD_SYMBOL).amount() == 0); - var expected = EntityCreator.userEntity().pln(PLN).usd(0).build(); + var expected = EntityCreator.user().pln(PLN).usd(0).build(); expect(expected); } @Transactional @Test void usdToPlnNoUsdCurrencyTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); var request = EntityCreator.exchangeRequest() .from(USD_SYMBOL) @@ -117,7 +116,7 @@ class CurrencyServiceTest extends RepositoryBasedTest { @Test void doubleExchangeTest() { var initialValue = 100; - var entity = EntityCreator.userEntity().pln(initialValue).build(); + var entity = EntityCreator.user().pln(initialValue).build(); userRepository.save(entity); var result1 = currencyService.exchange(EntityCreator.exchangeRequest() .from(PLN_SYMBOL) @@ -142,7 +141,7 @@ class CurrencyServiceTest extends RepositoryBasedTest { @Transactional @Test void insufficientFundsTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); var request = EntityCreator.exchangeRequest() .from(PLN_SYMBOL) @@ -176,7 +175,7 @@ class CurrencyServiceTest extends RepositoryBasedTest { .toSell(USD_SELL) .build(); assertThatThrownBy(() -> currencyService.exchange(entity)) - .isInstanceOf(UserNotFoundException.class); + .isInstanceOf(ExchangeFailedException.class); } @Test @@ -204,7 +203,7 @@ class CurrencyServiceTest extends RepositoryBasedTest { } private static Stream invalidPeselTest() { - return Stream.of("INVALID", INVALID_PESEL); + return Stream.of("INVALID", PESEL.replace('6', '7')); } } diff --git a/src/test/java/eu/ztsh/wymiana/service/UserServiceTest.java b/src/test/java/eu/ztsh/wymiana/service/UserServiceTest.java index 1ab7690..8a0f9fc 100644 --- a/src/test/java/eu/ztsh/wymiana/service/UserServiceTest.java +++ b/src/test/java/eu/ztsh/wymiana/service/UserServiceTest.java @@ -31,7 +31,7 @@ class UserServiceTest extends RepositoryBasedTest { @DisplayName("Create new user") void createNewUserTest() { userService.create(EntityCreator.userRequest().build()); - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); expect(entity); } @@ -64,7 +64,7 @@ class UserServiceTest extends RepositoryBasedTest { @Test @DisplayName("Try to create too young user") void youngUserTest() { - var request = EntityCreator.userRequest().pesel("").build(); + var request = EntityCreator.userRequest().pesel("08280959342").build(); assertThatThrownBy(() -> userService.create(request)) .isInstanceOf(ValidationFailedException.class) .hasMessageContaining(Adult.MESSAGE); @@ -74,7 +74,7 @@ class UserServiceTest extends RepositoryBasedTest { @Transactional @DisplayName("Get existing user") void getExistingUserTest() { - var entity = EntityCreator.userEntity().build(); + var entity = EntityCreator.user().build(); userRepository.save(entity); var userOptional = userService.get(EntityCreator.Constants.PESEL); var expected = UserMapper.entityToPojo(entity); diff --git a/src/test/java/eu/ztsh/wymiana/util/UserMapperTest.java b/src/test/java/eu/ztsh/wymiana/util/UserMapperTest.java index 11503aa..dc1eeb8 100644 --- a/src/test/java/eu/ztsh/wymiana/util/UserMapperTest.java +++ b/src/test/java/eu/ztsh/wymiana/util/UserMapperTest.java @@ -13,8 +13,13 @@ class UserMapperTest { @Test void entityToPojoTest() { - var entity = EntityCreator.userEntity().build(); - var expected = EntityCreator.user(); + var entity = EntityCreator.user().build(); + var expected = new User( + EntityCreator.Constants.NAME, + EntityCreator.Constants.SURNAME, + EntityCreator.Constants.PESEL, + Map.of("PLN", new Currency("PLN", EntityCreator.Constants.PLN)) + ); assertThat(UserMapper.entityToPojo(entity)) .usingRecursiveComparison() .isEqualTo(expected); @@ -22,8 +27,13 @@ class UserMapperTest { @Test void pojoToEntityTest() { - var entity = EntityCreator.user(); - var expected = EntityCreator.userEntity().build(); + var entity = new User( + EntityCreator.Constants.NAME, + EntityCreator.Constants.SURNAME, + EntityCreator.Constants.PESEL, + Map.of("PLN", new Currency("PLN", EntityCreator.Constants.PLN)) + ); + var expected = EntityCreator.user().build(); assertThat(UserMapper.pojoToEntity(entity)) .usingRecursiveComparison() .isEqualTo(expected); @@ -32,7 +42,7 @@ class UserMapperTest { @Test void requestToEntityTest() { var request = EntityCreator.userRequest().build(); - var expected = EntityCreator.userEntity().build(); + var expected = EntityCreator.user().build(); assertThat(UserMapper.requestToEntity(request)) .usingRecursiveComparison() .isEqualTo(expected); diff --git a/src/test/java/eu/ztsh/wymiana/web/ApplicationIntegrationTests.java b/src/test/java/eu/ztsh/wymiana/web/ApplicationIntegrationTests.java deleted file mode 100644 index 816cc99..0000000 --- a/src/test/java/eu/ztsh/wymiana/web/ApplicationIntegrationTests.java +++ /dev/null @@ -1,242 +0,0 @@ -package eu.ztsh.wymiana.web; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import eu.ztsh.wymiana.EntityCreator; -import eu.ztsh.wymiana.WireMockExtension; -import eu.ztsh.wymiana.util.UserMapper; -import org.junit.jupiter.api.ClassOrderer; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestClassOrder; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.web.reactive.server.WebTestClient; - -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.time.temporal.TemporalAdjusters; - -import static eu.ztsh.wymiana.EntityCreator.Constants.*; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Integration test suite. - * Contrary to the principle of test independence, tests are dependent on one another to create continuous suite. - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles("it") -@ExtendWith(WireMockExtension.class) -@TestMethodOrder(MethodOrderer.DisplayName.class) -@TestClassOrder(ClassOrderer.DisplayName.class) -class ApplicationIntegrationTests { - - private final WebTestClient webTestClient; - private final ObjectMapper objectMapper; - - @Autowired - public ApplicationIntegrationTests(WebTestClient webTestClient) { - this.webTestClient = webTestClient; - objectMapper = new ObjectMapper(); - } - - private String asJson(Object object) { - try { - return objectMapper.writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new IllegalStateException(e); - } - } - - @Nested - @TestMethodOrder(MethodOrderer.DisplayName.class) - @DisplayName("01: Context") - class ContextTests { - - @Test - @DisplayName("01.1: Load context") - void contextLoads() { - assertThat(webTestClient).isNotNull(); - webTestClient.get().uri("/actuator/health").exchange().expectBody().json("{\"status\":\"UP\"}"); - } - - } - - @Nested - @TestMethodOrder(MethodOrderer.DisplayName.class) - @DisplayName("02: User") - class UserTests { - - private static final String endpoint = "/api/user"; - - @Test - @DisplayName("02.1: Create valid user") - void createUserTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.userRequest().pln(100).build()) - .exchange() - .expectStatus().isNoContent(); - } - - @Test - @DisplayName("02.2: Try to create invalid user") - void createInvalidUserTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.userRequest().pesel(INVALID_PESEL).build()) - .exchange() - .expectStatus() - .isBadRequest(); - } - - @Test - @DisplayName("02.3: Try to create duplicated user") - void createDuplicatedUserTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.userRequest().build()) - .exchange() - .expectStatus().isEqualTo(409) - .expectBody(String.class).isEqualTo("User with PESEL %s already exists".formatted(PESEL)); - } - - @Test - @DisplayName("02.4: Get valid user") - void getValidUserTest() { - webTestClient.get() - .uri(endpoint.concat("/").concat(PESEL)) - .exchange() - .expectStatus().isOk() - .expectBody().json(asJson(UserMapper.entityToPojo(EntityCreator.userEntity().pln(100).build()))); - } - - @Test - @DisplayName("02.5: Try to get non-existing user") - void getNonExistingUserTest() { - webTestClient.get() - .uri(endpoint.concat("/").concat(ANOTHER_PESEL)) - .exchange() - .expectStatus().isNotFound(); - } - - @Test - @DisplayName("02.6: Get user by incorrect PESEL") - void getIncorrectPeselUserTest() { - webTestClient.get() - .uri(endpoint.concat("/").concat(INVALID_PESEL)) - .exchange() - .expectStatus().isBadRequest(); - } - - } - - @Nested - @TestMethodOrder(MethodOrderer.DisplayName.class) - @DisplayName("03: Exchange") - class ExchangeTests { - - private static final String URI_PATTERN = "/api/exchangerates/rates/c/usd/%s/"; - private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private static final String endpoint = "/api/exchange"; - - @Test - @DisplayName("03.1: Try to perform invalid money exchange: no data") - void noNbpDataTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.exchangeRequest() - .from(PLN_SYMBOL) - .to(USD_SYMBOL) - .toSell(PLN) - .build()) - .exchange() - .expectStatus().isEqualTo(500); - } - - @Test - @DisplayName("03.2: Perform valid money exchange") - void exchangeTest() { - var date = getTodayOrLastFriday(); - WireMockExtension.response( - URI_PATTERN.formatted(date), - 200, - asJson(EntityCreator.rates(date)) - ); - var expected = asJson(EntityCreator.user(100 - PLN, USD_BUY)); - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.exchangeRequest() - .from(PLN_SYMBOL) - .to(USD_SYMBOL) - .toSell(PLN) - .build()) - .exchange() - .expectStatus().isOk() - .expectBody().json(expected); - WireMockExtension.verifyGet(2, URI_PATTERN.formatted(date)); - } - - @Test - @DisplayName("03.3: Try to perform invalid money exchange: not existing user") - void exchangeNotExistingUserTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.exchangeRequest() - .pesel(ANOTHER_PESEL) - .from(PLN_SYMBOL) - .to(USD_SYMBOL) - .toSell(PLN) - .build()) - .exchange() - .expectStatus().isNotFound() - .expectBody(String.class).isEqualTo("User with PESEL %s not found".formatted(ANOTHER_PESEL)); - } - - @Test - @DisplayName("03.4: Try to perform invalid money exchange: invalid PESEL") - void invalidPeselTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.exchangeRequest() - .pesel(INVALID_PESEL) - .from(PLN_SYMBOL) - .to(USD_SYMBOL) - .toSell(PLN) - .build()) - .exchange() - .expectStatus().isBadRequest(); - } - - @Test - @DisplayName("03.5: Try to perform invalid money exchange: insufficient funds") - void insufficientFundsTest() { - webTestClient.post() - .uri(endpoint) - .bodyValue(EntityCreator.exchangeRequest() - .from(USD_SYMBOL) - .to(PLN_SYMBOL) - .toBuy(PLN) - .build()) - .exchange() - .expectStatus().isBadRequest(); - } - - private String getTodayOrLastFriday() { - var today = LocalDate.now(); - if (today.getDayOfWeek() == DayOfWeek.SATURDAY - || today.getDayOfWeek() == DayOfWeek.SUNDAY) { - today = today.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY)); - } - return today.format(dtf); - } - - } - -} diff --git a/src/test/resources/application-it.yaml b/src/test/resources/application-it.yaml deleted file mode 100644 index 198e366..0000000 --- a/src/test/resources/application-it.yaml +++ /dev/null @@ -1,2 +0,0 @@ -nbp: - baseurl: "http://localhost:38080"