diff --git a/README.md b/README.md index d450996..fe7dc50 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,11 @@ An example of a Spring-Boot application, which based on the port and adapters/he ## Implementing new adapter -The key concept is that the component scan for the adapter package is excluded in the application, so the unnecessary adapter beans won't be loaded into the application context, just the configured ones. +The whole component scan for the adapter package is excluded in the application, so the unnecessary adapter beans won't be loaded into the application context, just the configured ones. Each adapter defines her own spring configuration class, which is imported via the **@Import** annotation (on top of the application's main class) but getting only component scanned if the condition fulfills for it via **@ConditionalOnProperty** annotation. +Based on the below example if you define "spring-data-jpa" value as a persistence adapter in the application-[profile].yml, +then it will activate the corresponding Configuration class, which is going to component scan the underlying packages for spring beans. ### Example @@ -45,9 +47,30 @@ adapter: web: rest ``` +## Build and test with Maven +``` +mvn clean verify +``` + +**Building and verifying the application requires a running docker, since some tests are using +Testcontainers library! + + +### Test catalog and Maven lifecycle bindings + +| Test catalog type | Maven lifecycle | +|:-----------------:|:---------------:| +| Unit test | test | +| Component test | test | +| ArchUnit test | test | +| Integration test | verify | +| Functional test | verify | + ## API Documentation +You can access the API documentation locally at the following URL: + +[http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html) -You can access the live API documentation at http://localhost:8080/swagger-ui/index.html ![Preview](img/openapi-swagger-ui.PNG) diff --git a/app/pom.xml b/app/pom.xml index 5e6d301..4045d3b 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -26,6 +26,9 @@ 1.17.6 42.5.4 2.1.0 + 1.18.3 + hu.hirannor.hexagonal.HexagonalApplication + @@ -98,6 +101,14 @@ test + + org.testcontainers + junit-jupiter + ${junit-jupiter.version} + test + + + com.tngtech.archunit archunit-junit5 @@ -121,7 +132,7 @@ spring-boot-maven-plugin ${spring-boot.version} - hu.hirannor.hexagonal.HexagonalApplication + ${spring-boot-maven-plugin.mainClass} diff --git a/app/src/main/java/hu/hirannor/hexagonal/adapter/authentication/basic/BasicAuthenticationConfiguration.java b/app/src/main/java/hu/hirannor/hexagonal/adapter/authentication/basic/BasicAuthenticationConfiguration.java index 2db2122..3df452e 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/adapter/authentication/basic/BasicAuthenticationConfiguration.java +++ b/app/src/main/java/hu/hirannor/hexagonal/adapter/authentication/basic/BasicAuthenticationConfiguration.java @@ -4,7 +4,6 @@ import org.springframework.context.annotation.*; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; import org.springframework.security.core.userdetails.*; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; diff --git a/app/src/main/java/hu/hirannor/hexagonal/adapter/persistence/jpa/customer/CustomerJpaRepository.java b/app/src/main/java/hu/hirannor/hexagonal/adapter/persistence/jpa/customer/CustomerJpaRepository.java index c4f81c1..c41fbd4 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/adapter/persistence/jpa/customer/CustomerJpaRepository.java +++ b/app/src/main/java/hu/hirannor/hexagonal/adapter/persistence/jpa/customer/CustomerJpaRepository.java @@ -69,11 +69,11 @@ class CustomerJpaRepository implements CustomerRepository { public Customer updateDetails(final Customer domain) { if (domain == null) throw new IllegalArgumentException(ERR_CUSTOMER_IS_NULL); - LOGGER.debug("Changing customer details for customer value: {}", domain.customerId()); + LOGGER.debug("Changing customer details for customer id: {}", domain.customerId()); final CustomerModel model = customers.findByCustomerId(domain.customerId().asText()) .orElseThrow( - () -> new CustomerNotFound("Customer not found with value: " + domain) + () -> new CustomerNotFound("Customer not found with id: " + domain) ); final CustomerModel modifiedCustomer = CustomerModeller.applyChangesFrom(domain).to(model); @@ -86,7 +86,7 @@ public Customer updateDetails(final Customer domain) { public void deleteBy(final CustomerId id) { if (id == null) throw new IllegalArgumentException(ERR_CUSTOMER_ID_IS_NULL); - LOGGER.debug("Attempting to delete customer by value: {}", id); + LOGGER.debug("Attempting to delete customer by id: {}", id); customers.deleteByCustomerId(id.asText()); } @@ -111,7 +111,7 @@ public List findAllBy(final FilterCriteria criteria) { public Optional findBy(final CustomerId id) { if (id == null) throw new IllegalArgumentException(ERR_CUSTOMER_ID_IS_NULL); - LOGGER.debug("Fetching customer by value: {}", id); + LOGGER.debug("Fetching customer by id: {}", id); return customers.findByCustomerId(id.value()) .map(mapModelToDomain); diff --git a/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/CustomerManagementController.java b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/CustomerManagementController.java index 7cfe32c..8c84f03 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/CustomerManagementController.java +++ b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/CustomerManagementController.java @@ -10,10 +10,10 @@ import hu.hirannor.hexagonal.domain.customer.query.FilterCriteria; import hu.hirannor.hexagonal.infrastructure.adapter.DriverAdapter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; -import java.net.URI; import java.time.LocalDate; import java.util.List; import java.util.Optional; @@ -28,11 +28,8 @@ @DriverAdapter class CustomerManagementController implements CustomersApi { - private static final String BASE_PATH = "/customers/"; - private final Function mapCustomerToModel; private final Function mapRegisterCustomerToModel; - private final Function mapAddressModelToDomain; private final Function mapGenderModelToDomain; private final CustomerDisplay customers; @@ -52,7 +49,6 @@ class CustomerManagementController implements CustomersApi { deletion, CustomerMappingFactory.createCustomerToModelMapper(), CustomerMappingFactory.createRegisterCustomerModelToDomainMapper(), - CustomerMappingFactory.createAddressModelToAddressMapper(), CustomerMappingFactory.createGenderModelToDomainMapper() ); } @@ -63,7 +59,6 @@ class CustomerManagementController implements CustomersApi { final CustomerDeletion deletion, final Function mapCustomerToModel, final Function mapRegisterCustomerToModel, - final Function mapAddressModelToDomain, final Function mapGenderModelToDomain) { this.customers = customers; this.details = details; @@ -71,16 +66,17 @@ class CustomerManagementController implements CustomersApi { this.enrolling = enrolling; this.mapCustomerToModel = mapCustomerToModel; this.mapRegisterCustomerToModel = mapRegisterCustomerToModel; - this.mapAddressModelToDomain = mapAddressModelToDomain; this.mapGenderModelToDomain = mapGenderModelToDomain; } @Override public ResponseEntity changeDetails(final String customerId, final ChangeCustomerDetailsModel model) { - final ChangeCustomerDetails cmd = assembleCommand(customerId, model); + final ChangeCustomerDetails cmd = CustomerMappingFactory + .createChangeCustomerDetailsModelToDomainMapper(customerId) + .apply(model); - final Customer changedCustomer = details.changeDetailsBy(cmd); + final Customer changedCustomer = details.changeBy(cmd); final CustomerModel response = mapCustomerToModel.apply(changedCustomer); return ResponseEntity.ok(response); @@ -127,20 +123,7 @@ public ResponseEntity register(final RegisterCustomerModel model) final RegisterCustomer cmd = mapRegisterCustomerToModel.apply(model); final Customer registeredCustomer = enrolling.register(cmd); - return ResponseEntity.created( - URI.create(BASE_PATH + registeredCustomer.customerId().asText()) - ).body(mapCustomerToModel.apply(registeredCustomer)); + return new ResponseEntity<>(mapCustomerToModel.apply(registeredCustomer), HttpStatus.CREATED); } - private ChangeCustomerDetails assembleCommand(final String customerId, - final ChangeCustomerDetailsModel model) { - return new ChangeCustomerDetails.Builder() - .customerId(CustomerId.from(customerId)) - .fullName(FullName.from(model.getFirstName(), model.getLastName())) - .gender(mapGenderModelToDomain.apply(model.getGender())) - .birthDate(model.getBirthDate()) - .address(mapAddressModelToDomain.apply(model.getAddress())) - .email(EmailAddress.from(model.getEmailAddress())) - .assemble(); - } } diff --git a/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/ChangeCustomerDetailsModelToDomainMapper.java b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/ChangeCustomerDetailsModelToDomainMapper.java new file mode 100644 index 0000000..fe205db --- /dev/null +++ b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/ChangeCustomerDetailsModelToDomainMapper.java @@ -0,0 +1,49 @@ +package hu.hirannor.hexagonal.adapter.web.rest.customer.mapping; + +import hu.hirannor.hexagonal.adapter.web.rest.customer.model.*; +import hu.hirannor.hexagonal.domain.customer.*; +import hu.hirannor.hexagonal.domain.customer.command.ChangeCustomerDetails; + +import java.util.function.Function; + +/** + * Maps a {@link ChangeCustomerDetailsModel} model type to {@link ChangeCustomerDetails} domain type. + * + * @author Mate Karolyi + */ +class ChangeCustomerDetailsModelToDomainMapper implements Function { + + private final String customerId; + + private final Function mapGenderModelToDomain; + private final Function mapAddressModelToDomain; + + ChangeCustomerDetailsModelToDomainMapper(final String customerId) { + this( + customerId, + CustomerMappingFactory.createGenderModelToDomainMapper(), + CustomerMappingFactory.createAddressModelToAddressMapper() + ); + } + + ChangeCustomerDetailsModelToDomainMapper(final String customerId, + final Function mapGenderModelToDomain, + final Function mapAddressModelToDomain) { + this.customerId = customerId; + this.mapGenderModelToDomain = mapGenderModelToDomain; + this.mapAddressModelToDomain = mapAddressModelToDomain; + } + + + @Override + public ChangeCustomerDetails apply(final ChangeCustomerDetailsModel model) { + return new ChangeCustomerDetails.Builder() + .customerId(CustomerId.from(customerId)) + .fullName(FullName.from(model.getFirstName(), model.getLastName())) + .gender(mapGenderModelToDomain.apply(model.getGender())) + .birthDate(model.getBirthDate()) + .address(mapAddressModelToDomain.apply(model.getAddress())) + .email(EmailAddress.from(model.getEmailAddress())) + .assemble(); + } +} diff --git a/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/CustomerMappingFactory.java b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/CustomerMappingFactory.java index 2edd564..d82b889 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/CustomerMappingFactory.java +++ b/app/src/main/java/hu/hirannor/hexagonal/adapter/web/rest/customer/mapping/CustomerMappingFactory.java @@ -2,6 +2,7 @@ import hu.hirannor.hexagonal.adapter.web.rest.customer.model.*; import hu.hirannor.hexagonal.domain.customer.*; +import hu.hirannor.hexagonal.domain.customer.command.ChangeCustomerDetails; import hu.hirannor.hexagonal.domain.customer.command.RegisterCustomer; import java.util.function.Function; @@ -53,4 +54,16 @@ static Function createAddressModelToAddressMapper() { return new AddressModelToDomainMapper(); } + /** + * Create an instance of {@link ChangeCustomerDetailsModelToDomainMapper}, + * which maps a {@link ChangeCustomerDetailsModel} model type + * to a {@link ChangeCustomerDetails} domain type. + * + * @return an instance of {@link ChangeCustomerDetailsModelToDomainMapper} + */ + static Function createChangeCustomerDetailsModelToDomainMapper( + final String customerId) { + return new ChangeCustomerDetailsModelToDomainMapper(customerId); + } + } diff --git a/app/src/main/java/hu/hirannor/hexagonal/application/service/CustomerManagementService.java b/app/src/main/java/hu/hirannor/hexagonal/application/service/CustomerManagementService.java index 6f82205..9716306 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/application/service/CustomerManagementService.java +++ b/app/src/main/java/hu/hirannor/hexagonal/application/service/CustomerManagementService.java @@ -50,7 +50,7 @@ class CustomerManagementService implements } @Override - public Customer changeDetailsBy(final ChangeCustomerDetails cmd) { + public Customer changeBy(final ChangeCustomerDetails cmd) { if (cmd == null) throw new IllegalArgumentException("ChangeCustomerDetails command cannot be null!"); final Customer foundCustomer = customers.findBy(cmd.customerId()) @@ -64,7 +64,7 @@ public Customer changeDetailsBy(final ChangeCustomerDetails cmd) { messages.publish(updatedCustomer.listEvents()); updatedCustomer.clearEvents(); - LOGGER.info("Customer details for customer value: {} are updated successfully!", updatedCustomer.customerId()); + LOGGER.info("Customer details for customer id: {} are updated successfully!", updatedCustomer.customerId()); return updatedCustomer; } @@ -78,7 +78,7 @@ public void deleteBy(final CustomerId customerId) { () -> new CustomerNotFound(String.format(ERR_CUSTOMER_NOT_FOUND, customerId.asText())) ); - LOGGER.info("Attempting to delete customer by value: {}", customerId.asText()); + LOGGER.info("Attempting to delete customer by id: {}", customerId.asText()); customers.deleteBy(customerId); } @@ -96,7 +96,7 @@ public List displayAllBy(final FilterCriteria criteria) { public Optional displayBy(final CustomerId customerId) { if (customerId == null) throw new IllegalArgumentException(ERR_CUSTOMER_ID_IS_NULL); - LOGGER.info("Retrieving customer by value: {}", customerId); + LOGGER.info("Retrieving customer by id: {}", customerId); return customers.findBy(customerId); } diff --git a/app/src/main/java/hu/hirannor/hexagonal/application/usecase/CustomerModification.java b/app/src/main/java/hu/hirannor/hexagonal/application/usecase/CustomerModification.java index 8606d07..2ea5ba2 100644 --- a/app/src/main/java/hu/hirannor/hexagonal/application/usecase/CustomerModification.java +++ b/app/src/main/java/hu/hirannor/hexagonal/application/usecase/CustomerModification.java @@ -16,5 +16,5 @@ public interface CustomerModification { * @param cmd {@link ChangeCustomerDetails} including the modifications * @return {@link Customer} customer with modified details */ - Customer changeDetailsBy(ChangeCustomerDetails cmd); + Customer changeBy(ChangeCustomerDetails cmd); } diff --git a/app/src/main/resources/adapter/persistence/bundle-init.xml b/app/src/main/resources/adapter/persistence/bundle-init.xml index 9dca8dc..c817231 100644 --- a/app/src/main/resources/adapter/persistence/bundle-init.xml +++ b/app/src/main/resources/adapter/persistence/bundle-init.xml @@ -7,7 +7,4 @@ - - - \ No newline at end of file diff --git a/app/src/main/resources/adapter/persistence/dml/customers-demo-dml-1.0.0.xml b/app/src/main/resources/adapter/persistence/dml/customers-demo-dml-1.0.0.xml deleted file mode 100644 index 6799b13..0000000 --- a/app/src/main/resources/adapter/persistence/dml/customers-demo-dml-1.0.0.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/resources/application.yml b/app/src/main/resources/application.yml index 2bcfbb7..56b4934 100644 --- a/app/src/main/resources/application.yml +++ b/app/src/main/resources/application.yml @@ -1,6 +1,8 @@ logging: level: root: INFO + file: + path: logs spring: h2: diff --git a/app/src/main/resources/logback-spring.xml b/app/src/main/resources/logback-spring.xml index bfffb38..f5f246d 100644 --- a/app/src/main/resources/logback-spring.xml +++ b/app/src/main/resources/logback-spring.xml @@ -1,8 +1,5 @@ - - - @@ -11,10 +8,14 @@ - ${LOGS}/${LOG_FILE}.log + + UTF-8 + ${FILE_LOG_PATTERN} + + - ${LOG_FILE}.%d{yyyy-MM-dd}.gz + ${LOG_PATH}/spring-boot-hexagonal-ddd-application-%d{yyyy-MM-dd}.log.zip 30 3GB diff --git a/app/src/test/java/hu/hirannor/hexagonal/TestContainerBase.java b/app/src/test/java/hu/hirannor/hexagonal/TestContainerBase.java deleted file mode 100644 index fcccbb8..0000000 --- a/app/src/test/java/hu/hirannor/hexagonal/TestContainerBase.java +++ /dev/null @@ -1,22 +0,0 @@ -package hu.hirannor.hexagonal; - -import org.testcontainers.containers.PostgreSQLContainer; - -public class TestContainerBase { - - private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER; - - static { - POSTGRE_SQL_CONTAINER = - new PostgreSQLContainer<>("postgres:14") - .withReuse(true) - .withDatabaseName("test-db") - .withUsername("sa") - .withPassword("sa"); - - POSTGRE_SQL_CONTAINER.start(); - } - - public TestContainerBase() { - } -} diff --git a/app/src/test/java/hu/hirannor/hexagonal/architecture/TestArchTest.java b/app/src/test/java/hu/hirannor/hexagonal/architecture/TestArchTest.java index d9abfc3..d3c1539 100644 --- a/app/src/test/java/hu/hirannor/hexagonal/architecture/TestArchTest.java +++ b/app/src/test/java/hu/hirannor/hexagonal/architecture/TestArchTest.java @@ -6,7 +6,6 @@ import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.syntax.elements.GivenClassesConjunction; import com.tngtech.archunit.lang.syntax.elements.GivenMethodsConjunction; -import hu.hirannor.hexagonal.TestContainerBase; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.springframework.boot.test.context.TestConfiguration; @@ -39,8 +38,6 @@ class TestArchTest { .and() .areNotAnnotatedWith(TestConfiguration.class) .and() - .areNotAssignableTo(TestContainerBase.class) - .and() .areNotRecords(); testCases = diff --git a/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerDisplayingFunctionalTest.java b/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerDisplayingFunctionalTest.java index f0fa7fd..1b017bc 100644 --- a/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerDisplayingFunctionalTest.java +++ b/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerDisplayingFunctionalTest.java @@ -1,26 +1,31 @@ package hu.hirannor.hexagonal.functional; -import hu.hirannor.hexagonal.TestContainerBase; import hu.hirannor.hexagonal.adapter.web.rest.customer.api.CustomersApi; import hu.hirannor.hexagonal.adapter.web.rest.customer.model.*; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ActiveProfiles; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; import java.time.LocalDate; -import java.util.List; -import java.util.Optional; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; @ActiveProfiles("test") @DisplayName("CustomerDisplaying") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -class CustomerDisplayingFunctionalTest extends TestContainerBase { +class CustomerDisplayingFunctionalTest { + + @Container + private final PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>("postgres:14") + .withDatabaseName("test-db") + .withUsername("sa") + .withPassword("sa"); private final CustomersApi api; @@ -30,24 +35,33 @@ class CustomerDisplayingFunctionalTest extends TestContainerBase { } @Test - @DisplayName("should display all customer") + @DisplayName("should display all customer that are filtered with birthDateFrom") void testDisplayAll() { + final RegisterCustomerModel req1 = constructRequest("john.doe2@test.com", + LocalDate.of(1995, 2, 10)); + final RegisterCustomerModel req2 = constructRequest("john.doe3@test.com", + LocalDate.of(1996, 10, 10)); + api.register(req1); + api.register(req2); + final ResponseEntity> customers = api.displayAll( - Optional.empty(), + Optional.of(LocalDate.of(1995, 2, 10)), Optional.empty(), Optional.empty(), Optional.empty() ); assertThat(customers.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(customers.getBody().size()).isEqualTo(3); + assertThat(customers.getBody().size()).isEqualTo(2); } @Test @DisplayName("should display customer by id") void testDisplayById() { - final RegisterCustomerModel request = constructRequest(); - final CustomerModel expected = constructExpectedModel(); + final RegisterCustomerModel request = constructRequest("john.doe@test.com", + LocalDate.of(1992, 2, 10)); + final CustomerModel expected = constructExpectedModel("john.doe@test.com", + LocalDate.of(1992, 2, 10)); final ResponseEntity registeredCustomer = api.register(request); final String customerId = registeredCustomer.getBody().getCustomerId(); @@ -62,12 +76,12 @@ void testDisplayById() { } - private CustomerModel constructExpectedModel() { + private CustomerModel constructExpectedModel(final String email, final LocalDate birthDate) { return new CustomerModel() .firstName("John") .lastName("Doe") .gender(GenderModel.MALE) - .birthDate(LocalDate.of(1992, 2, 10)) + .birthDate(birthDate) .address( new AddressModel() .country(CountryModel.HUNGARY) @@ -75,15 +89,15 @@ private CustomerModel constructExpectedModel() { .city("Miskolc") .streetAddress("Szentgyörgy str 34") ) - .emailAddress("john.doe@test.com"); + .emailAddress(email); } - private RegisterCustomerModel constructRequest() { + private RegisterCustomerModel constructRequest(final String email, final LocalDate birthDate) { return new RegisterCustomerModel() .firstName("John") .lastName("Doe") .gender(GenderModel.MALE) - .birthDate(LocalDate.of(1992, 2, 10)) + .birthDate(birthDate) .address( new AddressModel() .country(CountryModel.HUNGARY) @@ -91,6 +105,6 @@ private RegisterCustomerModel constructRequest() { .city("Miskolc") .streetAddress("Szentgyörgy str 34") ) - .emailAddress("john.doe@test.com"); + .emailAddress(email); } } diff --git a/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerEnrollingFunctionalTest.java b/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerEnrollingFunctionalTest.java index 555cc22..b9f7585 100644 --- a/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerEnrollingFunctionalTest.java +++ b/app/src/test/java/hu/hirannor/hexagonal/functional/CustomerEnrollingFunctionalTest.java @@ -1,24 +1,31 @@ package hu.hirannor.hexagonal.functional; -import hu.hirannor.hexagonal.TestContainerBase; import hu.hirannor.hexagonal.adapter.web.rest.customer.api.CustomersApi; import hu.hirannor.hexagonal.adapter.web.rest.customer.model.*; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.ActiveProfiles; - +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import java.time.LocalDate; import static org.assertj.core.api.Assertions.assertThat; +@Testcontainers @ActiveProfiles("test") @DisplayName("CustomerEnrolling") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -class CustomerEnrollingFunctionalTest extends TestContainerBase { +class CustomerEnrollingFunctionalTest { + + @Container + private final PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>("postgres:14") + .withDatabaseName("test-db") + .withUsername("sa") + .withPassword("sa"); private final CustomersApi api;