From 1f715d85e17d2bf6c8d73df23e12252b993f74ff Mon Sep 17 00:00:00 2001 From: Sebastian Baltes Date: Tue, 13 May 2025 21:54:23 +0200 Subject: Add code or third assignment --- application/pom.xml | 80 ++++++++++++++++++++++ .../unibayreuth/se/campuscoffee/Application.java | 16 +++++ .../se/campuscoffee/LoadInitialData.java | 33 +++++++++ application/src/main/resources/application.yaml | 38 ++++++++++ application/src/main/resources/logback-spring.xml | 14 ++++ .../se/campuscoffee/AbstractSystemTest.java | 54 +++++++++++++++ .../se/campuscoffee/CampusCoffeeSystemTests.java | 65 ++++++++++++++++++ 7 files changed, 300 insertions(+) create mode 100644 application/pom.xml create mode 100644 application/src/main/java/de/unibayreuth/se/campuscoffee/Application.java create mode 100644 application/src/main/java/de/unibayreuth/se/campuscoffee/LoadInitialData.java create mode 100644 application/src/main/resources/application.yaml create mode 100644 application/src/main/resources/logback-spring.xml create mode 100644 application/src/test/java/de/unibayreuth/se/campuscoffee/AbstractSystemTest.java create mode 100644 application/src/test/java/de/unibayreuth/se/campuscoffee/CampusCoffeeSystemTests.java (limited to 'application') diff --git a/application/pom.xml b/application/pom.xml new file mode 100644 index 0000000..6754a87 --- /dev/null +++ b/application/pom.xml @@ -0,0 +1,80 @@ + + 4.0.0 + + + de.unibayreuth.se + parent + 0.0.1 + + + application + + + de.unibayreuth.se.campuscoffee.Application + + + + + de.unibayreuth.se + domain + ${project.version} + + + de.unibayreuth.se + api + ${project.version} + + + de.unibayreuth.se + data + ${project.version} + runtime + + + org.springframework.boot + spring-boot-testcontainers + + + org.testcontainers + postgresql + + + org.testcontainers + junit-jupiter + test + + + io.rest-assured + rest-assured + test + + + commons-logging + commons-logging + + + + + org.assertj + assertj-core + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + false + + + + maven-surefire-plugin + ${maven.plugin.surefire.version} + + + + \ No newline at end of file diff --git a/application/src/main/java/de/unibayreuth/se/campuscoffee/Application.java b/application/src/main/java/de/unibayreuth/se/campuscoffee/Application.java new file mode 100644 index 0000000..f471525 --- /dev/null +++ b/application/src/main/java/de/unibayreuth/se/campuscoffee/Application.java @@ -0,0 +1,16 @@ +package de.unibayreuth.se.campuscoffee; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +/** + * Main class to start the Spring Boot application in production. + */ +@SpringBootApplication +@ConfigurationPropertiesScan +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/application/src/main/java/de/unibayreuth/se/campuscoffee/LoadInitialData.java b/application/src/main/java/de/unibayreuth/se/campuscoffee/LoadInitialData.java new file mode 100644 index 0000000..a0cc1a8 --- /dev/null +++ b/application/src/main/java/de/unibayreuth/se/campuscoffee/LoadInitialData.java @@ -0,0 +1,33 @@ +package de.unibayreuth.se.campuscoffee; + +import de.unibayreuth.se.campuscoffee.domain.Pos; +import de.unibayreuth.se.campuscoffee.domain.TestFixtures; +import de.unibayreuth.se.campuscoffee.domain.ports.PosService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * Load initial data into the list via the list service from the business layer. + */ +@Component +@RequiredArgsConstructor +@Slf4j +@Profile("dev") +class LoadInitialData implements InitializingBean { + private final PosService posService; + + @Override + public void afterPropertiesSet() { + log.info("Deleting existing data..."); + posService.clear(); + log.info("Loading initial data..."); + List posList = TestFixtures.createPos(posService); + log.info("Loaded {} POS.", posList.size()); + log.info("Initial data loaded successfully."); + } +} \ No newline at end of file diff --git a/application/src/main/resources/application.yaml b/application/src/main/resources/application.yaml new file mode 100644 index 0000000..cf7430c --- /dev/null +++ b/application/src/main/resources/application.yaml @@ -0,0 +1,38 @@ +spring: + application: + name: campus-coffee + datasource: + driver-class-name: org.postgresql.Driver + jpa: + open-in-view: true + flyway: + enabled: true + locations: classpath:db/migration + validate-on-migrate: false +logging: + file: + name: campus-coffee.log + +--- +spring: + config: + activate: + on-profile: dev + datasource: + url: jdbc:postgresql://localhost:5432/postgres + username: postgres + password: postgres +server: + error: + include-message: always +springdoc: + api-docs: + path: /api/api-docs + swagger-ui: + path: /api/swagger-ui.html + +--- +spring: + config: + activate: + on-profile: test diff --git a/application/src/main/resources/logback-spring.xml b/application/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..4bb0b9b --- /dev/null +++ b/application/src/main/resources/logback-spring.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/application/src/test/java/de/unibayreuth/se/campuscoffee/AbstractSystemTest.java b/application/src/test/java/de/unibayreuth/se/campuscoffee/AbstractSystemTest.java new file mode 100644 index 0000000..6ca91ce --- /dev/null +++ b/application/src/test/java/de/unibayreuth/se/campuscoffee/AbstractSystemTest.java @@ -0,0 +1,54 @@ +package de.unibayreuth.se.campuscoffee; + +import de.unibayreuth.se.campuscoffee.domain.ports.PosService; +import io.restassured.RestAssured; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles({"test"}) +public abstract class AbstractSystemTest { + static final PostgreSQLContainer postgres = new PostgreSQLContainer<>( + DockerImageName.parse("postgres:17-alpine")) + .withUsername("postgres") + .withPassword("postgres") + .withDatabaseName("postgres"); + + @BeforeAll + static void beforeAll() { + postgres.start(); + } + + @AfterAll + static void afterAll() { + postgres.stop(); + } + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + registry.add("spring.datasource.username", postgres::getUsername); + registry.add("spring.datasource.password", postgres::getPassword); + } + + @Autowired + protected PosService posService; + + @LocalServerPort + private Integer port; + + @BeforeEach + void setUp() { + RestAssured.baseURI = "http://localhost:" + port; + posService.clear(); + } +} \ No newline at end of file diff --git a/application/src/test/java/de/unibayreuth/se/campuscoffee/CampusCoffeeSystemTests.java b/application/src/test/java/de/unibayreuth/se/campuscoffee/CampusCoffeeSystemTests.java new file mode 100644 index 0000000..195a36a --- /dev/null +++ b/application/src/test/java/de/unibayreuth/se/campuscoffee/CampusCoffeeSystemTests.java @@ -0,0 +1,65 @@ +package de.unibayreuth.se.campuscoffee; + +import de.unibayreuth.se.campuscoffee.api.dtos.PosDto; +import de.unibayreuth.se.campuscoffee.api.mapper.PosDtoMapper; +import de.unibayreuth.se.campuscoffee.domain.Pos; +import de.unibayreuth.se.campuscoffee.domain.TestFixtures; +import io.restassured.http.ContentType; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasSize; + +public class CampusCoffeeSystemTests extends AbstractSystemTest { + + @Autowired + private PosDtoMapper posDtoMapper; + + @Test + void getAllCreatedPos() { + List createdPosList = TestFixtures.createPos(posService); + + List retrievedPos = given() + .contentType(ContentType.JSON) + .when() + .get("/api/pos") + .then() + .statusCode(200) + .body(".", hasSize(createdPosList.size())) + .and() + .extract().jsonPath().getList("$", PosDto.class) + .stream() + .map(posDtoMapper::toDomain) + .toList(); + + assertThat(retrievedPos) + .usingRecursiveFieldByFieldElementComparatorIgnoringFields("createdAt", "updatedAt") // prevent issues due to differing timestamps after conversions + .containsExactlyInAnyOrderElementsOf(createdPosList); + } + + @Test + void getPosById() { + List createdPosList = TestFixtures.createPos(posService); + Pos createdPos = createdPosList.getFirst(); + + Pos retrievedPos = posDtoMapper.toDomain( + given() + .contentType(ContentType.JSON) + .when() + .get("/api/pos/{id}", createdPos.getId()) + .then() + .statusCode(200) + .extract().as(PosDto.class) + ); + + assertThat(retrievedPos) + .usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") // prevent issues due to differing timestamps after conversions + .isEqualTo(createdPos); + } + +} \ No newline at end of file -- cgit v1.2.3