diff options
author | Sebastian Baltes <Sebastian.Baltes@uni-bayreuth.de> | 2025-05-13 21:54:23 +0200 |
---|---|---|
committer | Sebastian Baltes <Sebastian.Baltes@uni-bayreuth.de> | 2025-05-13 21:54:23 +0200 |
commit | 1f715d85e17d2bf6c8d73df23e12252b993f74ff (patch) | |
tree | 3f430f6588e91c3e47793d7cd4f9957eb5bf4619 /application/src | |
parent | 21fc676c1b5a1d026e1489e9c8fabb80e652a50c (diff) | |
download | se25-assignment03-1f715d85e17d2bf6c8d73df23e12252b993f74ff.tar.gz se25-assignment03-1f715d85e17d2bf6c8d73df23e12252b993f74ff.zip |
Diffstat (limited to 'application/src')
6 files changed, 220 insertions, 0 deletions
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<Pos> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <include resource="org/springframework/boot/logging/logback/defaults.xml"/> + <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> + <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> + + <root level="INFO"> + <appender-ref ref="CONSOLE" /> + </root> + + <root level="INFO"> + <appender-ref ref="FILE" /> + </root> +</configuration> 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<Pos> createdPosList = TestFixtures.createPos(posService); + + List<Pos> 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<Pos> 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 |