chore: Initial import of FLEX training material

This commit is contained in:
Alexander Kobjolke 2024-11-07 21:02:53 +01:00
parent c01246d4f7
commit 12235acc42
1020 changed files with 53940 additions and 0 deletions

View file

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed</artifactId>
<version>2024.3.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>flexinale-distributed-test-integrated</artifactId>
<version>2024.3.0</version>
<name>Flexinale Distributed Test - testing done integrated in one app</name>
<description>Flexinale - FLEX case-study &quot;film festival&quot;, distributed services - testing done integrated in one app</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${apache-poi.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${apache-poi.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-besucherportal</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-common</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-common</artifactId>
<version>2024.3.0</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-security</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-security_api_contract</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-backoffice</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-backoffice_api_contract</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-ticketing</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.accso</groupId>
<artifactId>flexinale-distributed-ticketing_api_contract</artifactId>
<version>2024.3.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>${spotbugs-maven-plugin.version}</version>
<configuration>
<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>${findsecbugs-maven-plugin.version}</version>
</plugin>
</plugins>
</configuration>
<dependencies>
<!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>${spotbugs.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,216 @@
package de.accso.flexinale;
import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungCreatedEvent;
import de.accso.flexinale.backoffice.api_contract.event.VorfuehrungUpdatedEvent;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.besucherportal.api_contract.event.GutscheinEinloesenBeauftragtEvent;
import de.accso.flexinale.besucherportal.api_out.event.GutscheinEinloesenBeauftragtPublisher;
import de.accso.flexinale.besucherportal.api_in.event.TicketSubscriber;
import de.accso.flexinale.common.api.eventbus.EventBusFactory;
import de.accso.flexinale.common.infrastructure.eventbus.InMemorySyncEventBusSpy;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.ticketing.api_contract.event.OnlineKontingentChangedEvent;
import de.accso.flexinale.ticketing.api_contract.event.TicketGekauftEvent;
import de.accso.flexinale.ticketing.api_contract.event.model.TicketTO;
import de.accso.flexinale.ticketing.application.services.TicketService;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@DoNotCheckInArchitectureTests
public class End2EndEventsTest {
// Besucherportal
@Autowired
GutscheinEinloesenBeauftragtPublisher gutscheinEinloesenBeauftragtPublisher;
@Autowired
TicketSubscriber ticketSubscriber;
// Backoffice
@Autowired
VorfuehrungDao vorfuehrungDao;
@Autowired
FilmDao filmDao;
@Autowired
KinoDao kinoDao;
@Autowired
VorfuehrungPublisher vorfuehrungPublisher;
// Ticketing
@Autowired
TicketService ticketService;
@Autowired
KontingentDao kontingentDao;
// Bus
@Autowired
EventBusFactory eventBusFactory;
@Test
void testEnd2EndWithGutscheinEinloesenAndTicketKaufAndVorfuehrungenUpdates() {
// arrange
InMemorySyncEventBusSpy<GutscheinEinloesenBeauftragtEvent> gutscheinEinloesenBeauftragtBus =
(InMemorySyncEventBusSpy<GutscheinEinloesenBeauftragtEvent>)
eventBusFactory.createOrGetEventBusFor(GutscheinEinloesenBeauftragtEvent.class);
InMemorySyncEventBusSpy<TicketGekauftEvent> ticketGekauftBus =
(InMemorySyncEventBusSpy<TicketGekauftEvent>)
eventBusFactory.createOrGetEventBusFor(TicketGekauftEvent.class);
InMemorySyncEventBusSpy<VorfuehrungCreatedEvent> vorfuehrungCreatedBus =
(InMemorySyncEventBusSpy<VorfuehrungCreatedEvent>)
eventBusFactory.createOrGetEventBusFor(VorfuehrungCreatedEvent.class);
InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent> vorfuehrungUpdatedBus =
(InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent>)
eventBusFactory.createOrGetEventBusFor(VorfuehrungUpdatedEvent.class);
InMemorySyncEventBusSpy<OnlineKontingentChangedEvent> kontingentChangedBus =
(InMemorySyncEventBusSpy<OnlineKontingentChangedEvent>)
eventBusFactory.createOrGetEventBusFor(OnlineKontingentChangedEvent.class);
// ... create and publish Vorfuehrung
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
Iterator<KinoSaal> kinoSaalIterator = kino.kinoSaele.iterator();
KinoSaal kinoSaal1 = kinoSaalIterator.next();
KinoSaal kinoSaal2 = kinoSaalIterator.next();
kinoSaal2.anzahlPlaetze = new KinoSaal.AnzahlPlaetze(60);
kinoDao.save(kino);
// ... create Vorfuehrung
Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal1);
Vorfuehrung vorfuehrungCreated = vorfuehrungDao.save(vorfuehrung);
vorfuehrungPublisher.publishNewVorfuehrungen(List.of(vorfuehrung));
// check VorfuehrungCreated and OnlineKontingentChanged events on bus(es) and correlation IDs
assertThat(vorfuehrungCreatedBus.allEvents()).hasSize(1);
VorfuehrungCreatedEvent vorfuehrungCreatedEvent = vorfuehrungCreatedBus.allEvents().getFirst();
assertThat(kontingentChangedBus.allEvents()).hasSize(1);
OnlineKontingentChangedEvent kontingentChangedAfterVorfuehrungCreated = kontingentChangedBus.allEvents().getFirst();
assertThat(kontingentChangedAfterVorfuehrungCreated.correlationId()).isEqualTo(vorfuehrungCreatedEvent.correlationId());
// ... loese Gutscheine ein
Identifiable.Id besucherId = Identifiable.Id.of();
int anzahlGutscheine = 5;
gutscheinEinloesenBeauftragtPublisher.publishGutscheinEinloesenBeauftragtEvent(
vorfuehrung.id(), film.id(), besucherId, anzahlGutscheine);
assertThat(gutscheinEinloesenBeauftragtBus.allEvents()).hasSize(1);
GutscheinEinloesenBeauftragtEvent gutscheinEinloesenBeauftragtEvent = gutscheinEinloesenBeauftragtBus.allEvents().getFirst();
// ... Kaufe Tickets
assertThat(ticketService.findByBesucher(besucherId).size()).isEqualTo(anzahlGutscheine);
Integer kinoSaal1AnzahlPlaetze = getRawOrNull(kinoSaal1.anzahlPlaetze);
assertThat(kontingentDao.findByVorfuehrung(vorfuehrung.id()).get().getRestKontingentOnline().raw())
.isEqualTo(kinoSaal1AnzahlPlaetze/3 - anzahlGutscheine);
List<TicketTO> ticketsByBesucherGueltig = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
assertThat(ticketsByBesucherGueltig.size()).isEqualTo(anzahlGutscheine);
assertThat(ticketsByBesucherGueltig
.stream()
.filter(t -> {
Boolean gueltig = getRawOrNull(t.gueltig());
return !gueltig; })
.collect(Collectors.toList()))
.isEmpty();
// check TicketGekauft and OnlineKontingentChanged events on bus(es) and correlation IDs
assertThat(ticketGekauftBus.allEvents()).hasSize(anzahlGutscheine);
for (TicketGekauftEvent ticketGekauftEvent: ticketGekauftBus.allEvents()) {
assertThat(ticketGekauftEvent.correlationId()).isEqualTo(
gutscheinEinloesenBeauftragtEvent.correlationId());
}
assertThat(kontingentChangedBus.allEvents()).hasSize(2);
OnlineKontingentChangedEvent kontingentChangedAfterTicketKauf = kontingentChangedBus.allEvents().get(1);
assertThat(kontingentChangedAfterTicketKauf.correlationId()).isEqualTo(gutscheinEinloesenBeauftragtEvent.correlationId());
// ... update Vorfuehrung (KinoSaal)
Vorfuehrung vorfuehrungUpdate = new Vorfuehrung(vorfuehrungCreated.id, vorfuehrungCreated.version,
vorfuehrungCreated.zeit, vorfuehrungCreated.film, kinoSaal2);
vorfuehrungDao.save(vorfuehrungUpdate);
vorfuehrungPublisher.publishUpdatedVorfuehrungen(List.of(vorfuehrungUpdate));
// check VorfuehrungUpdated and OnlineKontingentChanged events on bus(es) and correlation IDs
assertThat(vorfuehrungUpdatedBus.allEvents()).hasSize(1);
VorfuehrungUpdatedEvent vorfuehrungUpdatedEvent = vorfuehrungUpdatedBus.allEvents().getFirst();
assertThat(kontingentChangedBus.allEvents()).hasSize(3);
OnlineKontingentChangedEvent kontingentChangedAfterVorfuehrungUpdated = kontingentChangedBus.allEvents().get(2);
assertThat(kontingentChangedAfterVorfuehrungUpdated.correlationId()).isEqualTo(vorfuehrungUpdatedEvent.correlationId());
// act, assert
// 1) Ticketing, Kontingente
List<Ticket> ticketsForBesucher = ticketService.findByBesucher(besucherId);
assertThat(ticketsForBesucher.size()).isEqualTo(anzahlGutscheine);
assertThat(ticketsForBesucher.stream().filter(t -> getRawOrNull(t.gueltig)).collect(Collectors.toList()))
.isEmpty();
Integer kinoSaal2AnzahlPlaetze = getRawOrNull(kinoSaal2.anzahlPlaetze);
assertThat(kontingentDao.findByVorfuehrung(vorfuehrung.id()).get().getRestKontingentOnline().raw())
.isEqualTo(kinoSaal2AnzahlPlaetze/3);
// 2) Besucherportal
List<TicketTO> ticketsByBesucherUngueltig = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
assertThat(ticketsByBesucherUngueltig.size()).isEqualTo(anzahlGutscheine);
assertThat(ticketsByBesucherUngueltig
.stream()
.filter(t -> getRawOrNull(t.gueltig()))
.collect(Collectors.toList()))
.isEmpty();
// act
// ... buy new Tickets
int newAnzahlGutscheine = anzahlGutscheine - 1;
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung.id(), film.id(), besucherId,newAnzahlGutscheine);
List<TicketTO> moreTickets = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
// assert
assertThat(moreTickets.size()).isEqualTo(anzahlGutscheine + newAnzahlGutscheine);
assertThat(moreTickets
.stream()
.filter(t -> getRawOrNull(t.gueltig()))
.toList().size())
.isEqualTo(newAnzahlGutscheine);
assertThat(moreTickets
.stream()
.filter(t -> {
Boolean gueltig = getRawOrNull(t.gueltig());
return ! gueltig; })
.toList().size())
.isEqualTo(anzahlGutscheine);
}
}

View file

@ -0,0 +1,21 @@
package de.accso.flexinale;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@SpringBootApplication
public class FlexinaleDistributedApplicationTestIntegrated {
public static void main(String[] args) {
SpringApplication.run(FlexinaleDistributedApplicationTestIntegrated.class, args);
}
@Bean
public PlatformTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}

View file

@ -0,0 +1,20 @@
package de.accso.flexinale;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@DoNotCheckInArchitectureTests
class FlexinaleDistributedApplicationTestIntegratedSmokeTest {
@Test
@SuppressWarnings("EmptyMethod")
void testLoadInitialApplicationContext() {
// nope
}
}

View file

@ -0,0 +1,350 @@
package de.accso.flexinale.backoffice.api_in.rest;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.*;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.besucherportal.api_in.event.FilmSubscriber;
import de.accso.flexinale.besucherportal.api_in.event.KinoSubscriber;
import de.accso.flexinale.besucherportal.api_in.event.KontingentSubscriber;
import de.accso.flexinale.besucherportal.api_in.event.VorfuehrungSubscriber;
import de.accso.flexinale.common.api.eventbus.EventBusFactory;
import de.accso.flexinale.common.infrastructure.eventbus.InMemorySyncEventBusSpy;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.ticketing.api_contract.event.OnlineKontingentChangedEvent;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@DoNotCheckInArchitectureTests
public class End2EndWithIntegratedInMemoryEventBusTest {
private static final Class<End2EndWithIntegratedInMemoryEventBusTest> CLAZZ =
End2EndWithIntegratedInMemoryEventBusTest.class;
private static final Logger LOGGER = LoggerFactory.getLogger(CLAZZ);
private static final String xlsDataFileForNewData =
"/de/accso/flexinale/backoffice/api_in/rest/NewDataForRestCallIntegrationTest.xlsx";
private static final String xlsDataFileForUpdatedData =
"/de/accso/flexinale/backoffice/api_in/rest/UpdatedDataForRestCallIntegrationTest.xlsx";
private static InputStream xlsDataFileForNewDataIS() {
return Objects.requireNonNull(CLAZZ.getResourceAsStream(xlsDataFileForNewData));
}
private static InputStream xlsDataFileForUpdatedDataIS() {
return Objects.requireNonNull(CLAZZ.getResourceAsStream(xlsDataFileForUpdatedData));
}
@Autowired
FilmRestController filmRestController;
@Autowired
KinoKinoSaalRestController kinoKinoSaalRestController;
@Autowired
VorfuehrungRestController vorfuehrungRestController;
@Autowired
FilmSubscriber filmSubscriber;
@Autowired
KinoSubscriber kinoSubscriber;
@Autowired
VorfuehrungSubscriber vorfuehrungSubscriber;
@Autowired
KontingentSubscriber kontingentSubscriber;
@Autowired
EventBusFactory eventBusFactory;
@Test
void testUploadNewAndUpdatedDataAndCheckForPublishedEventsOnTheEventBus() throws IOException {
// All data in the database is automatically deleted because of the property
// spring.jpa.hibernate.ddl-auto=create
// in the test application.properties
// Loading: order is important because of foreign key relations
// ---------------------------------------------------------------------------------------------------------
// Add new data
// Filme
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForNewDataIS())) {
testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4Filme(stream);
}
// Kino and KinoSaele
Collection<KinoSaal> newKinoSaele;
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForNewDataIS())) {
newKinoSaele = kinoKinoSaalRestController.loadKinoSaele(stream);
}
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForNewDataIS())) {
testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4Kinos(stream, newKinoSaele);
}
// Vorfuehrungen
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForNewDataIS())) {
testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4VorfuehrungenAndKontingente(stream);
}
// ---------------------------------------------------------------------------------------------------------
// Update existing data - Filme and Kinos and implicitely also VorfuehrungUpdated
// Filme
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForUpdatedDataIS())) {
testUploadUpdatedDataViaRestAndCheckPersistenceAndPublishedEvents4Filme(stream);
}
// Kino and KinoSaele
Collection<KinoSaal> updatedKinoSaele;
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForUpdatedDataIS())) {
updatedKinoSaele = kinoKinoSaalRestController.loadKinoSaele(stream);
}
try (BufferedInputStream stream = new BufferedInputStream(xlsDataFileForUpdatedDataIS())) {
testUploadUpdatedDataViaRestAndCheckPersistenceAndPublishedEvents4Kinos(stream, updatedKinoSaele);
}
// Vorfuehrungen
// do not test updates explicitely but VorfuehrungUpdated are created implicitely
// when ever a Vorfuehrung's Film or KinoSaal has changed
}
void testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4Filme(
final BufferedInputStream stream) throws IOException {
Set<String> filmIds = Set.of("F00", "F01", "F02", "F03");
// arrange
InMemorySyncEventBusSpy<FilmCreatedEvent> spy = (InMemorySyncEventBusSpy<FilmCreatedEvent>)
eventBusFactory.createOrGetEventBusFor(FilmCreatedEvent.class);
spy.clear();
// act
ResponseEntity<RestResponseMessage> result =
filmRestController.loadAndPersistAndPublishNewFilme(stream, xlsDataFileForNewData);
// assert
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(spy.size()).isEqualTo(4);
assertThat(spy.allEvents().stream()
.map(event -> event.film.id().id())
.collect(Collectors.toSet()))
.isEqualTo(filmIds);
for (String id: filmIds) {
Identifiable.Id filmId = Identifiable.Id.of(id);
assertThat(filmSubscriber.getCache().film(filmId)).isNotNull();
}
}
void testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4Kinos(
final BufferedInputStream stream,
final Collection<KinoSaal> kinoSaele) throws IOException {
Set<String> kinoIds = Set.of("K00", "K01", "K02", "K03");
// arrange
InMemorySyncEventBusSpy<KinoCreatedEvent> spy = (InMemorySyncEventBusSpy<KinoCreatedEvent>)
eventBusFactory.createOrGetEventBusFor(KinoCreatedEvent.class);
spy.clear();
// act
ResponseEntity<RestResponseMessage> result =
kinoKinoSaalRestController.loadAndPersistAndPublishNewKinosKinoSaele(stream, xlsDataFileForNewData, kinoSaele);
// assert
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(spy.size()).isEqualTo(4);
assertThat(spy.allEvents().stream()
.map(event -> event.kino.id().id())
.collect(Collectors.toSet()))
.isEqualTo(kinoIds);
for (String id: kinoIds) {
Identifiable.Id kinoId = Identifiable.Id.of(id);
assertThat(kinoSubscriber.getCache().kino(kinoId)).isNotNull();
assertThat(kinoSubscriber.getCache().kino(kinoId).kinoSaele()).isNotNull();
assertThat(kinoSubscriber.getCache().kino(kinoId).kinoSaele()).isNotEmpty();
assertThat(kinoSubscriber.getCache().kino(kinoId).kinoSaele().size()).isGreaterThanOrEqualTo(1);
kinoSubscriber.getCache().kino(kinoId).kinoSaele().forEach(kinoSaalTO -> {
assertThat(kinoSaalTO.kino()).isNotNull();
assertThat(kinoSaalTO.kino().id()).isEqualTo(kinoId);
});
}
}
void testUploadNewDataViaRestAndCheckPersistenceAndPublishedEvents4VorfuehrungenAndKontingente(
final BufferedInputStream stream) throws IOException {
Set<String> vorfuehrungIds = Set.of("V00", "V01", "V02", "V03", "V04",
"V05", "V06", "V07", "V08");
// arrange
InMemorySyncEventBusSpy<VorfuehrungCreatedEvent> spy4VorfuehrungCreatedEvent =
(InMemorySyncEventBusSpy<VorfuehrungCreatedEvent>) eventBusFactory.createOrGetEventBusFor(VorfuehrungCreatedEvent.class);
spy4VorfuehrungCreatedEvent.clear();
InMemorySyncEventBusSpy<OnlineKontingentChangedEvent> spy4OnlineKontingentChangedEvent =
(InMemorySyncEventBusSpy<OnlineKontingentChangedEvent>) eventBusFactory.createOrGetEventBusFor(OnlineKontingentChangedEvent.class);
spy4OnlineKontingentChangedEvent.clear();
// act
ResponseEntity<RestResponseMessage> result =
vorfuehrungRestController.loadAndPersistAndPublishNewVorfuehrungen(stream, xlsDataFileForNewData);
// assert
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(spy4VorfuehrungCreatedEvent.size()).isEqualTo(9);
assertThat(spy4VorfuehrungCreatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.id().id())
.collect(Collectors.toSet()))
.isEqualTo(vorfuehrungIds);
for (String vorfuehrungId: vorfuehrungIds) {
assertThat(vorfuehrungSubscriber.getCache().vorfuehrung(Identifiable.Id.of(vorfuehrungId))).isNotNull();
}
// ---------------------------------------------------------------------------------------------------------
// assert that Kontingente are created due to the uploaded Vorfuehrungen
assertThat(spy4OnlineKontingentChangedEvent.size()).isEqualTo(9);
assertThat(spy4OnlineKontingentChangedEvent.allEvents().stream()
.map(event -> event.onlineKontingent.vorfuehrungId().id()).collect(Collectors.toSet()))
.isEqualTo(vorfuehrungIds);
for (String id: vorfuehrungIds) {
Identifiable.Id vorfuehrungId = Identifiable.Id.of(id);
assertThat(kontingentSubscriber.getCache().getRestkontingentOnline(vorfuehrungId)).isNotNull();
}
}
// ---------------------------------------------------------------------------------------------------------
void testUploadUpdatedDataViaRestAndCheckPersistenceAndPublishedEvents4Filme(
final BufferedInputStream stream) throws IOException {
Set<String> changedFilmIds = Set.of("F00", "F01");
Set<String> vorfuehrungUpdatedIds = Set.of("V00", "V01", "V02", "V03");
// arrange
InMemorySyncEventBusSpy<FilmUpdatedEvent> spy4FilmUpdatedEvent = (InMemorySyncEventBusSpy<FilmUpdatedEvent>)
eventBusFactory.createOrGetEventBusFor(FilmUpdatedEvent.class);
spy4FilmUpdatedEvent.clear();
InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent> spy4VorfuehrungUpdatedEvent = (InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent>)
eventBusFactory.createOrGetEventBusFor(VorfuehrungUpdatedEvent.class);
spy4VorfuehrungUpdatedEvent.clear();
// act
ResponseEntity<RestResponseMessage> result =
filmRestController.loadAndPersistAndPublishNewFilme(stream, xlsDataFileForUpdatedData);
// assert
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(spy4FilmUpdatedEvent.size()).isEqualTo(2);
assertThat(spy4FilmUpdatedEvent.allEvents().stream()
.map(event -> event.film.id().id())
.collect(Collectors.toSet()))
.isEqualTo(changedFilmIds);
for (String id: changedFilmIds) {
Identifiable.Id filmId = Identifiable.Id.of(id);
assertThat(filmSubscriber.getCache().film(filmId)).isNotNull();
String titel = getRawOrNull(filmSubscriber.getCache().film(filmId).titel());
assertThat(titel.endsWith("_changed")).isTrue();
}
// assert VorfuehrungUpdated events
assertThat(spy4VorfuehrungUpdatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.id().id())
.collect(Collectors.toSet()))
.isEqualTo(vorfuehrungUpdatedIds);
assertThat(spy4VorfuehrungUpdatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.film().id().id())
.collect(Collectors.toSet()))
.isEqualTo(changedFilmIds);
}
void testUploadUpdatedDataViaRestAndCheckPersistenceAndPublishedEvents4Kinos(
final BufferedInputStream stream,
final Collection<KinoSaal> kinoSaele) throws IOException {
Set<String> changedKinoIds = Set.of("K00", "K01");
Set<String> vorfuehrungUpdatedIds = Set.of("V00", "V01", "V02", "V03");
// arrange
InMemorySyncEventBusSpy<KinoUpdatedEvent> spy4KinoUpdatedEvent = (InMemorySyncEventBusSpy<KinoUpdatedEvent>)
eventBusFactory.createOrGetEventBusFor(KinoUpdatedEvent.class);
spy4KinoUpdatedEvent.clear();
InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent> spy4VorfuehrungUpdatedEvent = (InMemorySyncEventBusSpy<VorfuehrungUpdatedEvent>)
eventBusFactory.createOrGetEventBusFor(VorfuehrungUpdatedEvent.class);
spy4VorfuehrungUpdatedEvent.clear();
// act
ResponseEntity<RestResponseMessage> result =
kinoKinoSaalRestController.loadAndPersistAndPublishNewKinosKinoSaele(stream, xlsDataFileForUpdatedData, kinoSaele);
// assert
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(spy4KinoUpdatedEvent.size()).isEqualTo(2);
assertThat(spy4KinoUpdatedEvent.allEvents().stream()
.map(event -> event.kino.id().id())
.collect(Collectors.toSet()))
.isEqualTo(changedKinoIds);
for (String id: changedKinoIds) {
Identifiable.Id kinoId = Identifiable.Id.of(id);
assertThat(kinoSubscriber.getCache().kino(kinoId)).isNotNull();
String kinoName = getRawOrNull(kinoSubscriber.getCache().kino(kinoId).name());
assertThat(kinoName.endsWith("_changed")).isTrue();
assertThat(kinoSubscriber.getCache().kino(kinoId).kinoSaele()).isNotNull();
assertThat(kinoSubscriber.getCache().kino(kinoId).kinoSaele()).isNotEmpty();
kinoSubscriber.getCache().kino(kinoId).kinoSaele().forEach(kinoSaalTO -> {
assertThat(kinoSaalTO.kino()).isNotNull();
String kinoSaalKinoName = getRawOrNull(kinoSaalTO.kino().name());
assertThat(kinoSaalKinoName.endsWith("_changed")).isTrue();
assertThat(kinoSaalTO.kino().id()).isEqualTo(kinoId);
});
}
// assert VorfuehrungUpdated events
assertThat(spy4VorfuehrungUpdatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.id().id())
.collect(Collectors.toSet()))
.isEqualTo(vorfuehrungUpdatedIds);
assertThat(spy4VorfuehrungUpdatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.kinoId().id())
.collect(Collectors.toSet()))
.isEqualTo(changedKinoIds);
assertThat(spy4VorfuehrungUpdatedEvent.allEvents().stream()
.map(event -> event.vorfuehrung.kinoSaal().kino().id().id())
.collect(Collectors.toSet()))
.isEqualTo(changedKinoIds);
}
}

View file

@ -0,0 +1,39 @@
package de.accso.flexinale.backoffice.api_in.rest;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.InputStream;
import static org.assertj.core.api.Assertions.assertThat;
class ExcelHelperTest {
@Test
void xlsFileHasExcelFormat() throws IOException {
// arrange
String xlsFile = "/de/accso/flexinale/backoffice/api_in/rest/NewDataForRestCallIntegrationTest.xlsx";
InputStream stream = this.getClass().getResourceAsStream(xlsFile);
// act
boolean result = ExcelHelper.isExcelFile(stream);
// assert
assertThat(result).isTrue();
}
@Test
void classFileDoesntHaveExcelFormat() throws IOException {
// arrange
String classFile = "/"
+ this.getClass().getCanonicalName().replace('.', '/')
+ ".class";
InputStream stream = this.getClass().getResourceAsStream(classFile);
// act
boolean result = ExcelHelper.isExcelFile(stream);
// assert
assertThat(result).isFalse();
}
}

View file

@ -0,0 +1,152 @@
package de.accso.flexinale.backoffice.api_in.rest;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.security.BenutzerDetailsService;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerDao;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import java.time.LocalDateTime;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createFilm;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@DoNotCheckInArchitectureTests
class RestControllerRetrieveDataTest {
@Autowired
BenutzerDao benutzerDao;
@Autowired
BenutzerDetailsService benutzerDetailsService;
@Autowired
FilmDao filmDao;
@Autowired
KinoDao kinoDao;
@Autowired
VorfuehrungDao vorfuehrungDao;
@Autowired
KontingentDao kontingentDao;
@Autowired
FilmRestController filmRestController;
@Autowired
KinoKinoSaalRestController kinoKinoSaalRestController;
@Autowired
VorfuehrungRestController vorfuehrungRestController;
@BeforeEach
public void createBenutzerCredentials() {
// arrange
BenutzerEntity benutzer = TestDataBuilder.createBenutzerEntity();
benutzer.encryptAndSetPassword("test");
// act
benutzerDao.save(benutzer);
UserDetails userDetails = benutzerDetailsService.loadUserByUsername (benutzer.login);
Authentication authToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),
userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
}
@Test
void testSmokeIntegrationPersistenceAndRestForFilmTest() {
// arrange
Film film = createFilm();
// act
Film savedFilm = filmDao.save(film);
// assert
assertThat(savedFilm.equalsByContent(film)).isTrue();
// act
Film searchedFilm = filmRestController.film(film.id().id());
// assert
assertThat(searchedFilm.equalsByContent(film)).isTrue();
}
@Test
void testSmokeIntegrationPersistenceAndRestForKinoKinoSaalTest() {
// arrange
Kino kino = TestDataBuilder.createKinoWithKinosaele(999);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
// act
Kino savedKino = kinoDao.save(kino);
// assert
assertThat(savedKino.equalsByContent(kino)).isTrue();
// act
Kino searchedKino = kinoKinoSaalRestController.kino(kino.id().id());
// assert
assertThat(searchedKino.equalsByContent(kino)).isTrue();
assertThat(searchedKino.kinoSaele).hasSize(1);
for (KinoSaal searchedKinoSaal : searchedKino.kinoSaele) {
assertThat(searchedKinoSaal.equalsByContent(kinoSaal)).isTrue();
}
}
@Test
void testSmokeIntegrationPersistenceAndRestForVorfuehrungAndKontingentSaalTest() {
// arrange
Film film = TestDataBuilder.createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele(999);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
Kontingent kontingent = TestDataBuilder.createKontingent(33, 33, 33, vorfuehrung);
// act
Film savedFilm = filmDao.save(film);
Kino savedKino = kinoDao.save(kino);
Vorfuehrung savedVorfuehrung = vorfuehrungDao.save(vorfuehrung);
Kontingent savedKontingent = kontingentDao.save(kontingent);
// assert
assertThat(savedFilm.equalsByContent(film)).isTrue();
assertThat(savedKino.equalsByContent(kino)).isTrue();
assertThat(savedVorfuehrung.equalsByContent(vorfuehrung)).isTrue();
assertThat(savedKontingent.equalsByContent(kontingent)).isTrue();
// act
Vorfuehrung searchedVorfuehrung = vorfuehrungRestController.vorfuehrung(vorfuehrung.id().id());
// assert
assertThat(searchedVorfuehrung.equalsByContent(vorfuehrung)).isTrue();
}
}

View file

@ -0,0 +1,34 @@
package de.accso.flexinale.backoffice.api_out.event.mapper;
import de.accso.flexinale.backoffice.api_contract.event.model.KinoTO;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import org.junit.jupiter.api.Test;
import java.util.Set;
import java.util.stream.Collectors;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@DoNotCheckInArchitectureTests
class KinoKinoSaal2KinoKinoSaalTOMapperTest {
@Test
void testMapKinoToKinoTO() {
// arrange
Kino kino = TestDataBuilder.createKinoWithKinosaele();
// act
KinoTO kinoTO = KinoKinoSaal2KinoKinoSaalTOMapper.mapKino(kino);
// assert
assertThat(kinoTO).isNotNull();
assertThat(kinoTO.id()).isEqualTo(kino.id());
assertThat(kinoTO.kinoSaele().size()).isEqualTo(kino.kinoSaele.size());
Set<Identifiable.Id> ksTOIds = kinoTO.kinoSaele().stream().map(ksTO -> ksTO.id()).collect(Collectors.toSet());
Set<Identifiable.Id> ksIds = kino.kinoSaele .stream().map(ks -> ks.id() ).collect(Collectors.toSet());
assertThat(ksTOIds).isEqualTo(ksIds);
}
}

View file

@ -0,0 +1,397 @@
package de.accso.flexinale.backoffice.infrastructure.persistence;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.Versionable;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.Optional;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class FKKsVEntityVersioningAndOptimisticLockTest {
@Autowired
private KinoDao kinoDao;
@Autowired
private FilmDao filmDao;
@Autowired
private VorfuehrungDao vorfuehrungDao;
@Test
void saveFilmInitiallySetsInitialVersionFromUnknownToZero() {
// arrange
Film newCreatedFilm = createFilm();
// act
filmDao.save(newCreatedFilm);
// assert
assertThat(newCreatedFilm.version).isEqualTo(Versionable.unknownVersion());
Optional<Film> searchedFilm = filmDao.findById(newCreatedFilm.id());
assertThat(searchedFilm.isPresent()).isTrue();
assertThat(searchedFilm.get().version).isEqualTo(Versionable.initialVersion());
// cleanup
filmDao.deleteById(newCreatedFilm.id());
// assert
assertThat(filmDao.findById(newCreatedFilm.id())).isEmpty();
}
@Test
void saveFilmThenChangeAndSaveAgainIncreasesItsVersion() {
// arrange
int initialVeryLongMovie = 24 * 60;
Integer changeToOneHourMovie = 60;
Film newCreatedFilm = createFilm();
newCreatedFilm.dauerInMinuten = new Film.DauerInMinuten(initialVeryLongMovie);
// act - save first time
filmDao.save(newCreatedFilm);
assertThat(newCreatedFilm.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Film> searched1stTimeFilm = filmDao.findById(newCreatedFilm.id());
assertThat(searched1stTimeFilm.isPresent()).isTrue();
// assert that version has been updated
Film filmToUpdateAndSaveAgain = searched1stTimeFilm.get();
assertThat(filmToUpdateAndSaveAgain.version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
filmToUpdateAndSaveAgain.dauerInMinuten = new Film.DauerInMinuten(changeToOneHourMovie); // change value on the loaded entity
filmDao.save(filmToUpdateAndSaveAgain);
// act - load again from db
Optional<Film> searched2ndTimeFilm = filmDao.findById(newCreatedFilm.id());
assertThat(searched2ndTimeFilm.isPresent()).isTrue();
Film filmLoadedAfterChange = searched2ndTimeFilm.get();
assertThat(filmLoadedAfterChange.version).isEqualTo(Versionable.Version.of(1)); // version increased after update
assertThat(filmLoadedAfterChange.id).isEqualTo(newCreatedFilm.id);
assertThat(filmLoadedAfterChange.titel).isEqualTo(newCreatedFilm.titel);
assertThat(filmLoadedAfterChange.imdbUrl).isEqualTo(newCreatedFilm.imdbUrl);
assertThat(filmLoadedAfterChange.dauerInMinuten.raw()).isEqualTo(changeToOneHourMovie);
// cleanup
filmDao.deleteById(newCreatedFilm.id());
// assert
assertThat(filmDao.findById(newCreatedFilm.id())).isEmpty();
}
@Test
void saveFilmThenChangeAndSaveAgainUsingOutdatedVersionIsAnError() {
// arrange
int initialVeryLongMovie = 24 * 60;
int changeToOneHourMovie = 60;
Film newCreatedFilm = createFilm();
newCreatedFilm.dauerInMinuten = new Film.DauerInMinuten(initialVeryLongMovie);
// act - save first time
filmDao.save(newCreatedFilm);
assertThat(newCreatedFilm.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Film> searched1stTimeFilm = filmDao.findById(newCreatedFilm.id());
assertThat(searched1stTimeFilm.isPresent()).isTrue();
// assert that version has been updated
assertThat(searched1stTimeFilm.get().version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
newCreatedFilm.dauerInMinuten = new Film.DauerInMinuten(changeToOneHourMovie); // change value but not the version
// act
Throwable thrown = catchThrowable(() -> filmDao.save(newCreatedFilm));
// assert
String expectedMessagePart =
"Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.accso.flexinale.backoffice.infrastructure.persistence.FilmEntity";
assertThat(thrown)
.isInstanceOf(OptimisticLockingFailureException.class)
.hasMessageContaining(expectedMessagePart);
// cleanup
filmDao.deleteById(newCreatedFilm.id());
// assert
assertThat(filmDao.findById(newCreatedFilm.id())).isEmpty();
}
// --------------------------------------------------------------------------------------------------------------
@Test
void saveKinoInitiallySetsInitialVersionFromUnknownToZero() {
// arrange
Kino newCreatedKino = createKinoWithKinosaele();
// act
kinoDao.save(newCreatedKino);
// assert
assertThat(newCreatedKino.version).isEqualTo(Versionable.unknownVersion());
Optional<Kino> searchedKino = kinoDao.findById(newCreatedKino.id());
assertThat(searchedKino.isPresent()).isTrue();
assertThat(searchedKino.get().version).isEqualTo(Versionable.initialVersion());
// cleanup
kinoDao.deleteById(newCreatedKino.id());
// assert
assertThat(kinoDao.findById(newCreatedKino.id())).isEmpty();
}
@Test
void saveKinoThenChangeAndSaveAgainIncreasesItsVersion() {
// arrange
String initialName = "initial";
String changeToNewName = "renamed";
Kino newCreatedKino = createKinoWithKinosaele();
newCreatedKino.name = new Kino.Name(initialName);
// act - save first time
kinoDao.save(newCreatedKino);
assertThat(newCreatedKino.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Kino> searched1stTimeKino = kinoDao.findById(newCreatedKino.id());
assertThat(searched1stTimeKino.isPresent()).isTrue();
// assert that version has been updated
Kino kinoToUpdateAndSaveAgain = searched1stTimeKino.get();
assertThat(kinoToUpdateAndSaveAgain.version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
kinoToUpdateAndSaveAgain.name = new Kino.Name(changeToNewName); // change value on the loaded entity
kinoDao.save(kinoToUpdateAndSaveAgain);
// act - load again from db
Optional<Kino> searched2ndTimeKino = kinoDao.findById(newCreatedKino.id());
assertThat(searched2ndTimeKino.isPresent()).isTrue();
Kino kinoLoadedAfterChange = searched2ndTimeKino.get();
assertThat(kinoLoadedAfterChange.version).isEqualTo(Versionable.Version.of(1)); // version increased after update
assertThat(kinoLoadedAfterChange.id).isEqualTo(newCreatedKino.id);
assertThat(kinoLoadedAfterChange.adresse).isEqualTo(newCreatedKino.adresse);
assertThat(kinoLoadedAfterChange.emailAdresse).isEqualTo(newCreatedKino.emailAdresse);
assertThat(kinoLoadedAfterChange.kinoSaele.size()).isEqualTo(newCreatedKino.kinoSaele.size());
assertThat(kinoLoadedAfterChange.name.raw()).isEqualTo(changeToNewName);
// cleanup
kinoDao.deleteById(newCreatedKino.id());
// assert
assertThat(kinoDao.findById(newCreatedKino.id())).isEmpty();
}
@Test
void saveKinoThenChangeAndSaveAgainUsingOutdatedVersionIsAnError() {
// arrange
String initialName = "initial";
String changeToNewName = "renamed";
Kino newCreatedKino = createKinoWithKinosaele();
newCreatedKino.name = new Kino.Name(initialName);
// act - save first time
kinoDao.save(newCreatedKino);
assertThat(newCreatedKino.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Kino> searched1stTimeKino = kinoDao.findById(newCreatedKino.id());
assertThat(searched1stTimeKino.isPresent()).isTrue();
// assert that version has been updated
assertThat(searched1stTimeKino.get().version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
newCreatedKino.name = new Kino.Name(changeToNewName); // change value but not the version
// act
Throwable thrown = catchThrowable(() -> kinoDao.save(newCreatedKino));
// assert
String expectedMessagePart =
"Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.accso.flexinale.backoffice.infrastructure.persistence.KinoEntity";
assertThat(thrown)
.isInstanceOf(OptimisticLockingFailureException.class)
.hasMessageContaining(expectedMessagePart);
// cleanup
kinoDao.deleteById(newCreatedKino.id());
// assert
assertThat(kinoDao.findById(newCreatedKino.id())).isEmpty();
}
// --------------------------------------------------------------------------------------------------------------
@Test
void saveVorfuehrungInitiallySetsInitialVersionFromUnknownToZero() {
// arrange
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
kino = kinoDao.save(kino);
LocalDateTime now = LocalDateTime.now();
KinoSaal kinoSaal = kino.kinoSaele.stream().findFirst().get();
Vorfuehrung newCreatedVorfuehrung = createVorfuehrung(now, film, kinoSaal);
// act
vorfuehrungDao.save(newCreatedVorfuehrung);
// assert
assertThat(newCreatedVorfuehrung.version).isEqualTo(Versionable.unknownVersion());
Optional<Vorfuehrung> searchedVorfuehrung = vorfuehrungDao.findById(newCreatedVorfuehrung.id());
assertThat(searchedVorfuehrung.isPresent()).isTrue();
assertThat(searchedVorfuehrung.get().version).isEqualTo(Versionable.initialVersion());
// cleanup
vorfuehrungDao.deleteById(newCreatedVorfuehrung.id());
filmDao.deleteById(film.id());
kinoDao.deleteById(kino.id());
// assert
assertThat(vorfuehrungDao.findById(newCreatedVorfuehrung.id())).isEmpty();
}
@Test
void saveVorfuehrungThenChangeAndSaveAgainIncreasesItsVersion() {
// arrange
LocalDateTime initialYesterday = LocalDateTime.now().withNano(0).minusDays(1);
LocalDateTime changeToToday = LocalDateTime.now().withNano(0);
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
kino = kinoDao.save(kino);
KinoSaal kinoSaal = kino.kinoSaele.stream().findFirst().get();
Vorfuehrung newCreatedVorfuehrung = createVorfuehrung(initialYesterday, film, kinoSaal);
// act - save first time
vorfuehrungDao.save(newCreatedVorfuehrung);
assertThat(newCreatedVorfuehrung.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Vorfuehrung> searched1stTimeVorfuehrung = vorfuehrungDao.findById(newCreatedVorfuehrung.id());
assertThat(searched1stTimeVorfuehrung.isPresent()).isTrue();
// assert that version has been updated
Vorfuehrung vorfuehrungToUpdateAndSaveAgain = searched1stTimeVorfuehrung.get();
assertThat(vorfuehrungToUpdateAndSaveAgain.version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
Vorfuehrung vorfuehrungChangedToUpdateAndSaveAgain =
new Vorfuehrung(vorfuehrungToUpdateAndSaveAgain.id, vorfuehrungToUpdateAndSaveAgain.version,
new Vorfuehrung.Zeit(changeToToday), // changed value on the loaded entity
vorfuehrungToUpdateAndSaveAgain.film, vorfuehrungToUpdateAndSaveAgain.kinoSaal);
vorfuehrungDao.save(vorfuehrungChangedToUpdateAndSaveAgain);
// act - load again from db
Optional<Vorfuehrung> searched2ndTimeVorfuehrung = vorfuehrungDao.findById(newCreatedVorfuehrung.id());
assertThat(searched2ndTimeVorfuehrung.isPresent()).isTrue();
Vorfuehrung vorfuehrungLoadedAfterChange = searched2ndTimeVorfuehrung.get();
assertThat(vorfuehrungLoadedAfterChange.version).isEqualTo(Versionable.Version.of(1)); // version increased after update
assertThat(vorfuehrungLoadedAfterChange.id).isEqualTo(newCreatedVorfuehrung.id);
assertThat(vorfuehrungLoadedAfterChange.film.equalsByContent(newCreatedVorfuehrung.film)).isTrue();
assertThat(vorfuehrungLoadedAfterChange.kinoSaal.equalsByContent(newCreatedVorfuehrung.kinoSaal)).isTrue();
assertThat(vorfuehrungLoadedAfterChange.zeit.raw()).isEqualTo(changeToToday);
// cleanup
vorfuehrungDao.deleteById(newCreatedVorfuehrung.id());
filmDao.deleteById(film.id());
kinoDao.deleteById(kino.id());
// assert
assertThat(vorfuehrungDao.findById(newCreatedVorfuehrung.id())).isEmpty();
}
@Test
void saveVorfuehrungThenChangeAndSaveAgainUsingOutdatedVersionIsAnError() {
// arrange
LocalDateTime initialYesterday = LocalDateTime.now().withNano(0).minusDays(1);
LocalDateTime changeToToday = LocalDateTime.now().withNano(0);
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
kino = kinoDao.save(kino);
KinoSaal kinoSaal = kino.kinoSaele.stream().findFirst().get();
Vorfuehrung newCreatedVorfuehrung = createVorfuehrung(initialYesterday, film, kinoSaal);
// act - save first time
vorfuehrungDao.save(newCreatedVorfuehrung);
assertThat(newCreatedVorfuehrung.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Vorfuehrung> searched1stTimeVorfuehrung = vorfuehrungDao.findById(newCreatedVorfuehrung.id());
assertThat(searched1stTimeVorfuehrung.isPresent()).isTrue();
// assert that version has been updated
assertThat(searched1stTimeVorfuehrung.get().version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
Vorfuehrung newCreatedAndChangedVorfuehrung =
new Vorfuehrung(newCreatedVorfuehrung.id, newCreatedVorfuehrung.version,
new Vorfuehrung.Zeit(changeToToday), // change value but not the version
newCreatedVorfuehrung.film, newCreatedVorfuehrung.kinoSaal);
// act
Throwable thrown = catchThrowable(() -> vorfuehrungDao.save(newCreatedAndChangedVorfuehrung));
// assert
String expectedMessagePart =
"Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.accso.flexinale.backoffice.infrastructure.persistence.VorfuehrungEntity";
assertThat(thrown)
.isInstanceOf(OptimisticLockingFailureException.class)
.hasMessageContaining(expectedMessagePart);
// cleanup
vorfuehrungDao.deleteById(newCreatedAndChangedVorfuehrung.id());
filmDao.deleteById(film.id());
kinoDao.deleteById(kino.id());
// assert
assertThat(vorfuehrungDao.findById(newCreatedAndChangedVorfuehrung.id())).isEmpty();
}
}

View file

@ -0,0 +1,124 @@
package de.accso.flexinale.backoffice.infrastructure.persistence;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.KinoSaalDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.Collectors;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class FKKsVPersistenceTest {
@Autowired
private FilmDao filmDao;
@Autowired
private KinoDao kinoDao;
@Autowired
private KinoSaalDao kinoSaalDao;
@Autowired
private VorfuehrungDao vorfuehrungDao;
@Test
void saveAndDeleteFilm() {
// arrange
Film film = createFilm();
// act
filmDao.save(film);
// assert
assertThat(filmDao.findById(film.id())).isNotEmpty();
// cleanup
filmDao.deleteById(film.id());
// assert
assertThat(filmDao.findById(film.id())).isEmpty();
}
@Test
void saveAndDeleteKinoAndKinoSaele() {
// arrange
Kino kino = createKinoWithKinosaele();
ArrayList<String> kinoSaeleIds = kino.kinoSaele.stream().map(it -> it.id().id()).collect(
Collectors.toCollection(ArrayList::new));
// act
kinoDao.save(kino);
// assert
assertThat(kinoDao.findById(kino.id())).isNotEmpty();
// cleanup
kinoDao.deleteById(kino.id());
// assert
assertThat(kinoDao.findById(kino.id())).isEmpty();
for (String kinoSaeleId: kinoSaeleIds) {
assertThat(kinoSaalDao.findById(Identifiable.Id.of(kinoSaeleId))).isEmpty();
}
}
@Test
void saveAndDeleteVorfuehrungAndKontingent() {
// arrange
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
kino = kinoDao.save(kino);
LocalDateTime now = LocalDateTime.now();
KinoSaal kinoSaal = kino.kinoSaele.stream().findFirst().get();
Vorfuehrung vorfuehrung = createVorfuehrung(now, film, kinoSaal);
// act
vorfuehrungDao.save(vorfuehrung);
// assert
Optional<Vorfuehrung> optionalSearchedVorfuehrung = vorfuehrungDao.findById(vorfuehrung.id());
assertThat(optionalSearchedVorfuehrung).isNotEmpty();
Vorfuehrung searchedVorfuehrung = optionalSearchedVorfuehrung.get();
LocalDateTime searchedVorfuehrungZeit = getRawOrNull(searchedVorfuehrung.zeit);
assertThat(searchedVorfuehrungZeit.getDayOfYear()).isEqualTo(now.getDayOfYear());
assertThat(searchedVorfuehrungZeit.getMinute()).isEqualTo(now.getMinute());
// cleanup
vorfuehrungDao.deleteById(vorfuehrung.id());
kinoDao.deleteById(kino.id());
filmDao.deleteById(film.id());
// assert
assertThat(vorfuehrungDao.findById(vorfuehrung.id())).isEmpty();
}
}

View file

@ -0,0 +1,31 @@
package de.accso.flexinale.backoffice.infrastructure.persistence.mapper;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.infrastructure.persistence.KinoEntity;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import org.junit.jupiter.api.Test;
import java.util.Set;
import java.util.stream.Collectors;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
class KinoKinoSaalEntity2KinoKinoSaalMapperTest {
@Test
void testMapKinoEntityToKino() {
// arrange
KinoEntity kinoEntity = TestDataBuilder.createKinoEntityWithKinosaele();
// act
Kino kino = KinoKinoSaalEntity2KinoKinoSaalMapper.mapKino(kinoEntity);
// assert
assertThat(kino).isNotNull();
assertThat(kino.id).isEqualTo(kino.id);
assertThat(kino.kinoSaele.size()).isEqualTo(kino.kinoSaele.size());
Set<String> ksEntityIds = kinoEntity.kinoSaele.stream().map(ks -> ks.id) .collect(Collectors.toSet());
Set<String> ksIds = kino.kinoSaele .stream().map(ks -> ks.id().id()).collect(Collectors.toSet());
assertThat(ksIds).isEqualTo(ksEntityIds);
}
}

View file

@ -0,0 +1,68 @@
package de.accso.flexinale.besucherportal.api_in.event;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.model.FilmTO;
import de.accso.flexinale.backoffice.api_out.event.FilmPublisher;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Collection;
import java.util.List;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createFilm;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class FilmSubscriberTest {
@Autowired
FilmSubscriber filmSubscriber;
@Autowired
FilmPublisher filmPublisher;
@Test
void testPublishAndSubscribeOfFilme() {
// arrange
Film film1 = createFilm();
Film film2 = createFilm();
Collection<Film> newFilms = List.of(film1, film2);
// act
filmPublisher.publishNewFilms(newFilms);
FilmTO filmTO1 = filmSubscriber.getCache().film(film1.id());
FilmTO filmTO2 = filmSubscriber.getCache().film(film2.id());
// assert
assertThat(filmTO1).isNotNull();
assertThat(filmTO1.id()).isEqualTo(film1.id());
assertThat(filmTO2).isNotNull();
assertThat(filmTO2.id()).isEqualTo(film2.id());
// act
List<FilmTO> filme = filmSubscriber.getCache().filme();
// assert
assertThat(filme.size()).isEqualTo(2);
// act
Collection<Film> sameFilmAgain = List.of(film1);
filmPublisher.publishNewFilms(sameFilmAgain);
// assert
assertThat(filmSubscriber.getCache().filme().size()).isEqualTo(2);
}
}

View file

@ -0,0 +1,71 @@
package de.accso.flexinale.besucherportal.api_in.event;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.model.KinoTO;
import de.accso.flexinale.backoffice.api_out.event.KinoPublisher;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Collection;
import java.util.List;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createKinoWithKinosaele;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class KinoSubscriberTest {
@Autowired
KinoSubscriber kinoSubscriber;
@Autowired
KinoPublisher kinoPublisher;
@Test
void testPublishAndSubscribeOfKinos() {
// arrange
Kino kino1 = createKinoWithKinosaele();
Kino kino2 = createKinoWithKinosaele();
Collection<Kino> newKinos = List.of(kino1, kino2);
kinoPublisher.publishNewKinos(newKinos);
// act
KinoTO kinoTO1 = kinoSubscriber.getCache().kino(kino1.id());
KinoTO kinoTO2 = kinoSubscriber.getCache().kino(kino2.id());
// assert
assertThat(kinoTO1).isNotNull();
assertThat(kinoTO1.id()).isEqualTo(kino1.id());
assertThat(kinoTO1.kinoSaele().size()).isEqualTo(kino1.kinoSaele.size());
assertThat(kinoTO2).isNotNull();
assertThat(kinoTO2.id()).isEqualTo(kino2.id());
assertThat(kinoTO2.kinoSaele().size()).isEqualTo(kino2.kinoSaele.size());
// act
List<KinoTO> kinos = kinoSubscriber.getCache().kinos();
// assert
assertThat(kinos.size()).isEqualTo(2);
// act
Collection<Kino> sameKinoAgain = List.of(kino1);
kinoPublisher.publishNewKinos(sameKinoAgain);
// assert
assertThat(kinoSubscriber.getCache().kinos().size()).isEqualTo(2);
}
}

View file

@ -0,0 +1,125 @@
package de.accso.flexinale.besucherportal.api_in.event;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_out.event.FilmPublisher;
import de.accso.flexinale.backoffice.api_out.event.KinoPublisher;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.besucherportal.api_out.event.GutscheinEinloesenBeauftragtPublisher;
import de.accso.flexinale.besucherportal.api_contract.event.GutscheinEinloesenBeauftragtEvent;
import de.accso.flexinale.besucherportal.api_contract.event.model.GutscheinEinloesenAuftragTO;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Versionable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createFilm;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createKinoWithKinosaele;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class KontingentSubscriberTest {
@Autowired
KinoPublisher kinoPublisher;
@Autowired
VorfuehrungPublisher vorfuehrungPublisher;
@Autowired
FilmPublisher filmPublisher;
@Autowired
KontingentSubscriber kontingentSubscriber;
@Autowired
private GutscheinEinloesenBeauftragtPublisher gutscheinEinloesenBeauftragtPublisher;
Vorfuehrung vorfuehrung1;
Vorfuehrung vorfuehrung2;
@BeforeEach
void prepareVorfuehrungenAnKontingente() {
// arrange for all tests
Film film = createFilm();
Collection<Film> newFilms = new ArrayList<>();
newFilms.add(film);
filmPublisher.publishNewFilms(newFilms);
Kino kino = createKinoWithKinosaele();
// kino has 3 kinosaele
Iterator<KinoSaal> kinoSaalIterator = kino.kinoSaele.iterator();
KinoSaal kinoSaal1 = kinoSaalIterator.next();
kinoSaal1.anzahlPlaetze = new KinoSaal.AnzahlPlaetze(120);
KinoSaal kinoSaal2 = kinoSaalIterator.next();
kinoSaal2.anzahlPlaetze = new KinoSaal.AnzahlPlaetze(99);
Collection<Kino> newKinos = new ArrayList<>();
newKinos.add(kino);
kinoPublisher.publishNewKinos(newKinos);
vorfuehrung1 = new Vorfuehrung(Identifiable.Id.of(), new Vorfuehrung.Zeit(LocalDateTime.now()), film, kinoSaal1);
vorfuehrung2 = new Vorfuehrung(Identifiable.Id.of(), new Vorfuehrung.Zeit(LocalDateTime.now()), film, kinoSaal2);
Collection<Vorfuehrung> newVorfuehrungen = List.of(vorfuehrung1, vorfuehrung2);
vorfuehrungPublisher.publishNewVorfuehrungen(newVorfuehrungen);
}
@Test
void testRestKontingentOnlineWhenVorfuehrungInVerkaufGeben() {
// act
int restKontingentOnlineForVorfuehrung1 = kontingentSubscriber.getCache().getRestkontingentOnline(vorfuehrung1.id());
int restKontingentOnlineForVorfuehrung2 = kontingentSubscriber.getCache().getRestkontingentOnline(vorfuehrung2.id());
// assert
assertThat(restKontingentOnlineForVorfuehrung1).isEqualTo(120/3);
assertThat(restKontingentOnlineForVorfuehrung2).isEqualTo(99/3);
}
@Test
void testRestKontingentOnlineWhenTicketsKaufen() {
// arrange
GutscheinEinloesenAuftragTO gutschein2 = new GutscheinEinloesenAuftragTO(Identifiable.Id.of(), Versionable.initialVersion(),
vorfuehrung1.film.id(), vorfuehrung1.id(), Identifiable.Id.of(),
new GutscheinEinloesenAuftragTO.AnzahlTickets(2));
gutscheinEinloesenBeauftragtPublisher.post(GutscheinEinloesenBeauftragtEvent.class,
new GutscheinEinloesenBeauftragtEvent(gutschein2));
GutscheinEinloesenAuftragTO gutschein5 = new GutscheinEinloesenAuftragTO(Identifiable.Id.of(), Versionable.initialVersion(),
vorfuehrung2.film.id(), vorfuehrung2.id(), Identifiable.Id.of(),
new GutscheinEinloesenAuftragTO.AnzahlTickets(5));
gutscheinEinloesenBeauftragtPublisher.post(GutscheinEinloesenBeauftragtEvent.class,
new GutscheinEinloesenBeauftragtEvent(gutschein5));
// act
int restKontingentOnlineForVorfuehrung1 = kontingentSubscriber.getCache().getRestkontingentOnline(vorfuehrung1.id());
int restKontingentOnlineForVorfuehrung2 = kontingentSubscriber.getCache().getRestkontingentOnline(vorfuehrung2.id());
// assert
assertThat(restKontingentOnlineForVorfuehrung1).isEqualTo(120/3 - 2);
assertThat(restKontingentOnlineForVorfuehrung2).isEqualTo(99/3 - 5);
}
}

View file

@ -0,0 +1,83 @@
package de.accso.flexinale.besucherportal.api_in.event;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.model.VorfuehrungTO;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class VorfuehrungSubscriberTest {
@Autowired
VorfuehrungSubscriber vorfuehrungSubscriber;
@Autowired
VorfuehrungPublisher vorfuehrungPublisher;
@Test
void testPublishAndSubscribeOfVorfuehrungen() {
// arrange
Film film1 = createFilm();
Film film2 = createFilm();
Kino kino = createKinoWithKinosaele();
Iterator<KinoSaal> kinoSaalIterator = kino.kinoSaele.iterator();
KinoSaal kinosaal1 = kinoSaalIterator.next();
KinoSaal kinosaal2 = kinoSaalIterator.next();
Vorfuehrung vorfuehrung1 = createVorfuehrung(LocalDateTime.now(), film1, kinosaal1);
Vorfuehrung vorfuehrung2 = createVorfuehrung(LocalDateTime.now(), film2, kinosaal2);
Collection<Vorfuehrung> newVorfuehrungen = List.of(vorfuehrung1, vorfuehrung2);
vorfuehrungPublisher.publishNewVorfuehrungen(newVorfuehrungen);
// act
VorfuehrungTO vorfuehrungTO1 = vorfuehrungSubscriber.getCache().vorfuehrung(vorfuehrung1.id());
VorfuehrungTO vorfuehrungTO2 = vorfuehrungSubscriber.getCache().vorfuehrung(vorfuehrung2.id());
// assert
assertThat(vorfuehrungTO1).isNotNull();
assertThat(vorfuehrungTO1.id()).isEqualTo(vorfuehrung1.id());
assertThat(vorfuehrungTO1.kinoSaal().id()).isEqualTo(vorfuehrung1.kinoSaal.id());
assertThat(vorfuehrungTO2).isNotNull();
assertThat(vorfuehrungTO2.id()).isEqualTo(vorfuehrung2.id());
assertThat(vorfuehrungTO2.kinoSaal().id()).isEqualTo(vorfuehrung2.kinoSaal.id());
// act
Collection<Vorfuehrung> sameVorfuehrungAgain = List.of(vorfuehrung2);
vorfuehrungPublisher.publishNewVorfuehrungen(sameVorfuehrungAgain);
// act
List<VorfuehrungTO> vorfuehrungTOSbyFilmId = vorfuehrungSubscriber.getCache().vorfuehrungenByFilmId(film2.id());
// assert
assertThat(vorfuehrungTOSbyFilmId.size()).isEqualTo(1);
VorfuehrungTO vorfuehrungTOByFilmId = vorfuehrungTOSbyFilmId.getFirst();
assertThat(vorfuehrungTOByFilmId.id()).isEqualTo(vorfuehrung2.id());
}
}

View file

@ -0,0 +1,277 @@
package de.accso.flexinale.besucherportal.api_in.web;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_out.event.FilmPublisher;
import de.accso.flexinale.backoffice.api_out.event.KinoPublisher;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.besucherportal.api_contract.event.GutscheinEinloesenBeauftragtEvent;
import de.accso.flexinale.besucherportal.api_contract.event.model.GutscheinEinloesenAuftragTO;
import de.accso.flexinale.besucherportal.api_out.event.GutscheinEinloesenBeauftragtPublisher;
import de.accso.flexinale.besucherportal.api_in.event.TicketSubscriber;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.common.shared_kernel.Versionable;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.api_contract.event.model.TicketTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createFilm;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createKinoWithKinosaele;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
class GutscheinEinloesenBeauftragtSubscriberAndSortingTest {
@Autowired
private TicketSubscriber ticketSubscriber;
@Autowired
private GutscheinEinloesenBeauftragtPublisher gutscheinEinloesenBeauftragtPublisher;
@Autowired
private KinoPublisher kinoPublisher;
@Autowired
private VorfuehrungPublisher vorfuehrungPublisher;
@Autowired
FilmPublisher filmPublisher;
private Identifiable.Id besucherId;
private Vorfuehrung vorfuehrung1;
@BeforeEach
void prepare() {
// arrange for all tests
Film film = createFilm();
Collection<Film> newFilms = new ArrayList<>();
newFilms.add(film);
filmPublisher.publishNewFilms(newFilms);
Kino kino = createKinoWithKinosaele(120);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Collection<Kino> newKinos = new ArrayList<>();
newKinos.add(kino);
kinoPublisher.publishNewKinos(newKinos);
LocalDateTime beginnVorfuehrung1 = LocalDateTime.of(2022, 11, 29, 16, 0);
vorfuehrung1 = TestDataBuilder.createVorfuehrung(beginnVorfuehrung1, film, kinoSaal);
Vorfuehrung vorfuehrung2 = TestDataBuilder.createVorfuehrung(beginnVorfuehrung1.plusHours(24), film, kinoSaal);
Vorfuehrung vorfuehrung3 = TestDataBuilder.createVorfuehrung(beginnVorfuehrung1.plusHours(3), film, kinoSaal);
Collection<Vorfuehrung> newVorfuehrungen = List.of(vorfuehrung1, vorfuehrung2, vorfuehrung3);
vorfuehrungPublisher.publishNewVorfuehrungen(newVorfuehrungen);
besucherId = Identifiable.Id.of();
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung1.id(), vorfuehrung1.film.id(), besucherId, 2);
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung2.id(), vorfuehrung2.film.id(), besucherId, 3);
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung3.id(), vorfuehrung3.film.id(), besucherId, 4);
}
@Test
void testTicketKauf() {
// arrange
Identifiable.Id anotherBesucherId = Identifiable.Id.of();
List<TicketTO> tickets = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
assertThat(tickets.size()).isEqualTo(9);
// arbitrary besucher who has not yet bought tickets
List<TicketTO> shouldNotContainTickets = ticketSubscriber.getCache().ticketsByBesucher(anotherBesucherId);
assertThat(shouldNotContainTickets).isEmpty();
}
@Test
void testTicketKaufButNotEnoughKontingent() {
// arrange
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung1.id(), vorfuehrung1.film.id(), besucherId, 100);
// act
List<TicketTO> shouldOnlyContainTicketsFromPrepare = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
// assert
assertThat(shouldOnlyContainTicketsFromPrepare.size()).isEqualTo(9);
}
@Test
void testTicketKaufWithDuplicateEvent() {
// arrange
Identifiable.Id anotherBesucherId = Identifiable.Id.of();
GutscheinEinloesenAuftragTO gutschein = new GutscheinEinloesenAuftragTO(Identifiable.Id.of(), Versionable.initialVersion(),
vorfuehrung1.film.id(), vorfuehrung1.id(), anotherBesucherId,
new GutscheinEinloesenAuftragTO.AnzahlTickets(2));
GutscheinEinloesenBeauftragtEvent gutscheinEinloesenBeauftragtEvent =
new GutscheinEinloesenBeauftragtEvent(gutschein);
// act
gutscheinEinloesenBeauftragtPublisher.post(GutscheinEinloesenBeauftragtEvent.class, gutscheinEinloesenBeauftragtEvent);
List<TicketTO> tickets = ticketSubscriber.getCache().ticketsByBesucher(anotherBesucherId);
// assert
assertThat(tickets.size()).isEqualTo(2);
// act
// pulish same event again
gutscheinEinloesenBeauftragtPublisher.post(GutscheinEinloesenBeauftragtEvent.class, gutscheinEinloesenBeauftragtEvent);
List<TicketTO> ticketsAfterSecondEvent = ticketSubscriber.getCache().ticketsByBesucher(anotherBesucherId);
// assert
assertThat(ticketsAfterSecondEvent.size()).isEqualTo(2);
}
@Test
void testTicketKaufWithSameButNotDuplicateEvent() {
// arrange
Identifiable.Id anotherBesucherId = Identifiable.Id.of();
// act
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung1.id(), vorfuehrung1.film.id(), anotherBesucherId, 2);
List<TicketTO> tickets = ticketSubscriber.getCache().ticketsByBesucher(anotherBesucherId);
// assert
assertThat(tickets.size()).isEqualTo(2);
// act
gutscheinEinloesenBeauftragtPublisher
.publishGutscheinEinloesenBeauftragtEvent(vorfuehrung1.id(), vorfuehrung1.film.id(), anotherBesucherId, 2);
List<TicketTO> ticketsAfterSecondEvent = ticketSubscriber.getCache().ticketsByBesucher(anotherBesucherId);
// assert
assertThat(ticketsAfterSecondEvent.size()).isEqualTo(4);
}
@Test
void testSortAndMapGueltigeTicketsPerDay() {
// act
List<TicketTO> tickets = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
// assert
assertThat(tickets.size()).isEqualTo(9);
List<List<VorfuehrungMitAnzahlTicketsTO>> vorfuehrungenTickets
= TicketSorter.sortAndMapTicketsPerDay(tickets, ticketSubscriber.getCache());
// The outer list contains one list for each day. There are tickets for 2 different days
assertThat(vorfuehrungenTickets.size()).isEqualTo(2);
// assert order by Zeit
VorfuehrungMitAnzahlTicketsTO last = null;
for (VorfuehrungMitAnzahlTicketsTO vMATTO: vorfuehrungenTickets.stream()
.flatMap(inner -> inner.stream()).toList())
{
if (last != null) {
LocalDateTime lastZeit = getRawOrNull(last.zeit());
LocalDateTime vMATTOZeit = getRawOrNull(vMATTO.zeit());
assertThat(lastZeit).isBeforeOrEqualTo(vMATTOZeit);
}
last = vMATTO;
}
// assert sorting
// Day 1: 2 Vorfuehrungen a 2 resp 3 tickets
List<VorfuehrungMitAnzahlTicketsTO> vorfuehrungenOfDay1 = vorfuehrungenTickets.getFirst();
assertThat(vorfuehrungenOfDay1.size()).isEqualTo(2);
LocalDateTime zeit0 = getRawOrNull(vorfuehrungenOfDay1.get(0).zeit());
LocalDateTime zeit1 = getRawOrNull(vorfuehrungenOfDay1.get(1).zeit());
assertThat(zeit0).isBeforeOrEqualTo(zeit1);
assertThat(vorfuehrungenOfDay1.get(0).anzahlGueltigeTickets().raw()).isEqualTo(2);
assertThat(vorfuehrungenOfDay1.get(1).anzahlGueltigeTickets().raw()).isEqualTo(4);
// Day 2: 1 Vorfuehrung
List<VorfuehrungMitAnzahlTicketsTO> vorfuehrungenOfDay2 = vorfuehrungenTickets.get(1);
assertThat(vorfuehrungenOfDay2.size()).isEqualTo(1);
assertThat(vorfuehrungenOfDay2.getFirst().anzahlGueltigeTickets().raw()).isEqualTo(3);
}
@Test
void testSortAndMapGueltigeAndUngueltigeTicketsPerDay() {
// arrange: invalidate a ticket
List<TicketTO> tickets1 = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
TicketTO aTicket = tickets1.getFirst();
TicketTO ungueltigesTicket = new TicketTO(aTicket.id(), aTicket.version(), aTicket.filmId(), aTicket.vorfuehrungId(), aTicket.besucherId(), aTicket.verkaufsKanal(), new TicketTO.Gueltig(false));
ticketSubscriber.getCache().addOrUpdate(ungueltigesTicket);
// act
List<TicketTO> tickets = ticketSubscriber.getCache().ticketsByBesucher(besucherId);
// assert
assertThat(tickets.size()).isEqualTo(9);
List<List<VorfuehrungMitAnzahlTicketsTO>> vorfuehrungenTickets
= TicketSorter.sortAndMapTicketsPerDay(tickets, ticketSubscriber.getCache());
// The outer list contains one list for each day. There are tickets for 2 different days
assertThat(vorfuehrungenTickets.size()).isEqualTo(2);
// assert order by Zeit
VorfuehrungMitAnzahlTicketsTO last = null;
for (VorfuehrungMitAnzahlTicketsTO vMATTO: vorfuehrungenTickets.stream()
.flatMap(inner -> inner.stream()).toList())
{
if (last != null) {
LocalDateTime lastZeit = getRawOrNull(last.zeit());
LocalDateTime vMATTOZeit = getRawOrNull(vMATTO.zeit());
assertThat(lastZeit).isBeforeOrEqualTo(vMATTOZeit);
}
last = vMATTO;
}
// assert sorting
// Day 1: 2 Vorfuehrungen a 2 resp 3 tickets
List<VorfuehrungMitAnzahlTicketsTO> vorfuehrungenOfDay1 = vorfuehrungenTickets.getFirst();
assertThat(vorfuehrungenOfDay1.size()).isEqualTo(2);
LocalDateTime zeit0 = getRawOrNull(vorfuehrungenOfDay1.get(0).zeit());
LocalDateTime zeit1 = getRawOrNull(vorfuehrungenOfDay1.get(1).zeit());
assertThat(zeit0).isBeforeOrEqualTo(zeit1);
// Day 2: 1 Vorfuehrung
List<VorfuehrungMitAnzahlTicketsTO> vorfuehrungenOfDay2 = vorfuehrungenTickets.get(1);
assertThat(vorfuehrungenOfDay2.size()).isEqualTo(1);
// anzahl gueltige Tickets
assertThat(vorfuehrungenOfDay1.get(0).anzahlGueltigeTickets().raw()
+ vorfuehrungenOfDay1.get(1).anzahlGueltigeTickets().raw()
+ vorfuehrungenOfDay2.getFirst().anzahlGueltigeTickets().raw()).isEqualTo(8);
// anzahl ungueltige Tickets
assertThat(vorfuehrungenOfDay1.get(0).anzahlUngueltigeTickets().raw()
+ vorfuehrungenOfDay1.get(1).anzahlUngueltigeTickets().raw()
+ vorfuehrungenOfDay2.getFirst().anzahlUngueltigeTickets().raw()).isEqualTo(1);
}
}

View file

@ -0,0 +1,83 @@
package de.accso.flexinale.security.infrastructure.persistence;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.createBenutzerEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class BenutzerSecurityAndPersistenceTest {
@Autowired
private BenutzerDao benutzerDao;
@Test
void saveAndFindAndDeleteBesucher() {
// arrange
BenutzerEntity benutzer = createBenutzerEntity();
Identifiable.Id benutzerId = Identifiable.Id.of(benutzer.id);
// act
benutzer = benutzerDao.save(benutzer);
// assert
assertThat(benutzerDao.findById(benutzerId)).isNotEmpty();
// cleanup
benutzerDao.deleteById(benutzerId);
// assert
assertThat(benutzerDao.findById(benutzerId)).isEmpty();
}
@Test
void saveAndFindByLoginAndDelete() {
// arrange
BenutzerEntity benutzer = createBenutzerEntity();
Identifiable.Id benutzerId = Identifiable.Id.of(benutzer.id);
// act
benutzer = benutzerDao.save(benutzer);
// assert
assertThat(benutzerDao.findByLogin(benutzer.login)).isNotEmpty();
// cleanup
benutzerDao.deleteById(benutzerId);
// assert
assertThat(benutzerDao.findById(benutzerId)).isEmpty();
}
@Test
void saveAndFindByNameAndDelete() {
// arrange
BenutzerEntity benutzer = createBenutzerEntity();
Identifiable.Id benutzerId = Identifiable.Id.of(benutzer.id);
// act
benutzer = benutzerDao.save(benutzer);
// assert
assertThat(benutzerDao.findByName(benutzer.name)).isNotEmpty();
// cleanup
benutzerDao.deleteById(benutzerId);
// assert
assertThat(benutzerDao.findById(benutzerId)).isEmpty();
}
}

View file

@ -0,0 +1,107 @@
package de.accso.flexinale.shared_code_for_test;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.backoffice.infrastructure.persistence.KinoEntity;
import de.accso.flexinale.backoffice.infrastructure.persistence.KinoSaalEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.common.shared_kernel.Versionable;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
import static de.accso.flexinale.common.shared_kernel.Identifiable.Id.uuidString;
@DoNotCheckInArchitectureTests
public final class TestDataBuilder {
public static Film createFilm() {
return createFilm("testfilm", "testurl", 42);
}
public static Film createFilm(String titel, String imdbUrl, Integer dauerInMinuten) {
return new Film(Identifiable.Id.of(), new Film.Titel(titel), new Film.ImdbUrl(imdbUrl), new Film.DauerInMinuten(dauerInMinuten));
}
public static Kino createKinoWithKinosaele() {
return createKinoWithKinosaele(120, 111, 112);
}
public static Kino createKinoWithKinosaele(int... anzahlPlaetze) {
Kino kino = new Kino(Identifiable.Id.of(), new Kino.Name("Helion"),
new Kino.Adresse("Kinostrasse 1"),
new Kino.EmailAdresse("contact.helion@fl.ex"), new HashSet<>());
Set<KinoSaal> saele = new HashSet<>();
int counter = 1;
for (int anzahl: anzahlPlaetze) {
saele.add(new KinoSaal(Identifiable.Id.of(), new KinoSaal.Name("saal " + counter), new KinoSaal.AnzahlPlaetze(anzahl), kino));
}
kino.addSaele(saele);
return kino;
}
public static KinoEntity createKinoEntityWithKinosaele() {
return createKinoEntityWithKinosaele(120, 111, 112);
}
public static KinoEntity createKinoEntityWithKinosaele(int... anzahlPlaetze) {
KinoEntity kino = new KinoEntity(uuidString(), Versionable.unknownVersion().version(), "Helion", "Kinostrasse 1",
"contact.helion@fl.ex");
Set<KinoSaalEntity> saele = new HashSet<>();
int counter = 1;
for (int anzahl: anzahlPlaetze) {
saele.add(new KinoSaalEntity(uuidString(), Versionable.unknownVersion().version(), "saal " + counter, anzahl, kino));
}
kino.kinoSaele = saele;
return kino;
}
public static BenutzerEntity createBenutzerEntity() {
String benutzerId = Identifiable.Id.of().id();
return new BenutzerEntity(benutzerId,
"testlogin" + benutzerId, // needs to be unique
"test" + benutzerId + "@fl.ex", // needs to be unique
"testname", "testvorname");
}
public static Vorfuehrung createVorfuehrung() {
KinoSaal kinoSaal = createKinoWithKinosaele(100).kinoSaele.iterator().next();
return createVorfuehrung(LocalDateTime.now(), createFilm(), kinoSaal);
}
public static Vorfuehrung createVorfuehrung(LocalDateTime zeit, Film film, KinoSaal kinoSaal) {
return new Vorfuehrung(Identifiable.Id.of(), new Vorfuehrung.Zeit(zeit), film, kinoSaal);
}
public static Ticket createTicket(Film film, Vorfuehrung vorfuehrung, BenutzerEntity besucher) {
return createTicket(film, vorfuehrung, besucher, Ticket.VerkaufsKanal.ONLINE);
}
public static Ticket createTicket(Film film, Vorfuehrung vorfuehrung, BenutzerEntity besucher, Ticket.VerkaufsKanal kanal) {
return new Ticket(Identifiable.Id.of(), film.id(), vorfuehrung.id(), Identifiable.Id.of(besucher.id), kanal);
}
public static Kontingent createKontingent(int gesamtKapazitaetVerkauf, int quoteOnline, Vorfuehrung vorfuehrung) {
return new Kontingent(Identifiable.Id.of(), gesamtKapazitaetVerkauf, quoteOnline, vorfuehrung.id());
}
public static Kontingent createKontingent(int restKontingentOnline, int restKontingentZentral,
int restKontingentKinokasse, Vorfuehrung vorfuehrung) {
return new Kontingent(Identifiable.Id.of(),
new Kontingent.RestKontingent(restKontingentOnline),
new Kontingent.RestKontingent(restKontingentZentral),
new Kontingent.RestKontingent(restKontingentKinokasse),
vorfuehrung.id());
}
}

View file

@ -0,0 +1,152 @@
package de.accso.flexinale.ticketing.application.services;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.application.services.TicketService;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
class TicketCRUDTest {
@Autowired
TicketService ticketService;
@Autowired
private FilmDao filmDao;
@Autowired
private KinoDao kinoDao;
@Autowired
private TicketDao ticketDao;
@Autowired
private VorfuehrungDao vorfuehrungDao;
@Autowired
private KontingentDao kontingentDao;
private BenutzerEntity besucher;
@BeforeEach
void prepareDataForTicketKauf() {
// arrange for all tests
besucher = TestDataBuilder.createBenutzerEntity();
}
@AfterEach
void cleanupDatabase() {
ticketDao.deleteAll();
kontingentDao.deleteAll();
}
@Test
void testFindByBesucherOrderByZeit() {
// arrange
Film film = TestDataBuilder.createFilm();
filmDao.save(film);
Kino kino = TestDataBuilder.createKinoWithKinosaele(120, 300, 600);
kinoDao.save(kino);
Vorfuehrung vorfuehrung1 = TestDataBuilder.createVorfuehrung(LocalDateTime.now(),
film, kino.kinoSaele.iterator().next());
Vorfuehrung vorfuehrung2 = TestDataBuilder.createVorfuehrung(LocalDateTime.now().plusHours(50),
film, kino.kinoSaele.iterator().next());
Vorfuehrung vorfuehrung3 = TestDataBuilder.createVorfuehrung(LocalDateTime.now().plusHours(100),
film, kino.kinoSaele.iterator().next());
vorfuehrungDao.save(vorfuehrung1);
vorfuehrungDao.save(vorfuehrung2);
vorfuehrungDao.save(vorfuehrung3);
// arrange
int kontingentGesamt = 120;
int quoteOnline = 33;
Kontingent kontingent1 = TestDataBuilder.createKontingent(kontingentGesamt, quoteOnline, vorfuehrung1);
Kontingent kontingent2 = TestDataBuilder.createKontingent(kontingentGesamt, quoteOnline, vorfuehrung2);
Kontingent kontingent3 = TestDataBuilder.createKontingent(kontingentGesamt, quoteOnline, vorfuehrung3);
kontingentDao.save(kontingent1);
kontingentDao.save(kontingent2);
kontingentDao.save(kontingent3);
// act
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung1.id(), film.id(), besucher.id(), 2);
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung2.id(), film.id(), besucher.id(), 3);
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung3.id(), film.id(), besucher.id(), 4);
List<Ticket> tickets = ticketService.findByBesucher(besucher.id());
// assert
assertThat(tickets.size()).isEqualTo(9);
// all tickets are ordered by zeit
List<Vorfuehrung> vorfuehrungen = tickets.stream()
.map(t -> vorfuehrungDao.findById(t.vorfuehrungId).get())
.toList();
LocalDateTime lastZeit = LocalDateTime.MIN;
for (Vorfuehrung v : vorfuehrungen) {
LocalDateTime zeit = getRawOrNull(v.zeit);
assertThat(zeit).isAfterOrEqualTo(lastZeit);
lastZeit = zeit;
}
}
@Test
void testSaveAndDeleteTicket() {
// arrange
Film film = TestDataBuilder.createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
Ticket ticket = TestDataBuilder.createTicket(film, vorfuehrung, besucher, Ticket.VerkaufsKanal.KINOKASSE);
// act
ticketDao.save(ticket);
// assert
Optional<Ticket> ticketOptional = ticketDao.findById(ticket.id());
assertThat(ticketOptional).isNotEmpty();
// cleanup
ticketDao.deleteById(ticket.id());
// assert
assertThat(ticketDao.findById(ticket.id())).isEmpty();
}
}

View file

@ -0,0 +1,113 @@
package de.accso.flexinale.ticketing.application.services;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.application.services.TicketService;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class TicketKaufTest {
@Autowired
TicketService ticketService;
@Autowired
private TicketDao ticketDao;
@Autowired
private KontingentDao kontingentDao;
private BenutzerEntity besucher;
private final int quoteOnline = 33;
@BeforeEach
void prepareDataForTicketKauf() {
// arrange for all tests
besucher = TestDataBuilder.createBenutzerEntity();
}
@AfterEach
void cleanupDatabase() {
ticketDao.deleteAll();
kontingentDao.deleteAll();
}
@Test
void testLoeseGutscheineOnlineFuerVorfuehrungEin_Ticket() {
// arrange
Film film = TestDataBuilder.createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
int kontingentGesamt = 120;
Kontingent kontingent = TestDataBuilder.createKontingent(kontingentGesamt, quoteOnline, vorfuehrung);
kontingentDao.save(kontingent);
int anzahlGutscheine = 10;
// act
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung.id(), film.id(), besucher.id(), anzahlGutscheine);
// assert
int anzahlTickets = ticketDao.gesamtZahlDerTicketsFuer(Identifiable.Id.of(besucher.id));
assertThat(anzahlTickets).isEqualTo(anzahlGutscheine);
List<Ticket> tickets = ticketDao.findAll();
assertThat(tickets.size()).isEqualTo(anzahlGutscheine);
}
@Test
void testLoeseGutscheineOnlineFuerVorfuehrungEin_Kontingent() {
// arrange
Film film = TestDataBuilder.createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
int kontingentGesamt = 120;
Kontingent kontingent = TestDataBuilder.createKontingent(kontingentGesamt, quoteOnline, vorfuehrung);
kontingentDao.save(kontingent);
int anzahlGutscheine = 10;
// act
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung.id(), film.id(), besucher.id(), anzahlGutscheine);
// assert
Optional<Kontingent> kontingent1 = kontingentDao.findById(kontingent.id());
assertThat(kontingent1.isPresent()).isTrue();
assertThat(kontingent1.get().getRestKontingentOnline().raw()).isEqualTo(40 - anzahlGutscheine);
}
}

View file

@ -0,0 +1,106 @@
package de.accso.flexinale.ticketing.application.services;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.model.KinoTO;
import de.accso.flexinale.backoffice.api_contract.event.model.VorfuehrungTO;
import de.accso.flexinale.backoffice.api_out.event.mapper.KinoKinoSaal2KinoKinoSaalTOMapper;
import de.accso.flexinale.backoffice.api_out.event.mapper.Vorfuehrung2VorfuehrungTOMapper;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class VorfuehrungUpdatedTest {
@Autowired
TicketService ticketService;
@Autowired
private TicketDao ticketDao;
@Autowired
private KontingentDao kontingentDao;
@AfterEach
void cleanupDatabase() {
ticketDao.deleteAll();
kontingentDao.deleteAll();
}
@Test
void testAktualisiereVorfuehrung(){
// arrange
Film film = TestDataBuilder.createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele();
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
kinoSaal.anzahlPlaetze = new KinoSaal.AnzahlPlaetze(120);
VorfuehrungTO vorfuehrung = Vorfuehrung2VorfuehrungTOMapper.map(
TestDataBuilder.createVorfuehrung(LocalDateTime.now(), film, kinoSaal));
// act
ticketService.gebeVorfuehrungInDenVerkauf(vorfuehrung.id(), getRawOrNull(vorfuehrung.kinoSaal().anzahlPlaetze()));
Identifiable.Id besucherId = Identifiable.Id.of();
ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrung.id(), vorfuehrung.film().id(),
besucherId, 10);
Optional<Kontingent> kontingentOptional = kontingentDao.findByVorfuehrung(vorfuehrung.id());
List<Ticket> tickets = ticketService.findByBesucher(besucherId);
// assert
assertThat(tickets.size()).isEqualTo(10);
assertThat(kontingentOptional.get().getRestKontingentOnline().raw()).isEqualTo(120/3 -10);
// arrange - aktualisiere Vorfuehrung
Kino newKino = TestDataBuilder.createKinoWithKinosaele();
KinoSaal newKinoSaal = kino.kinoSaele.iterator().next();
newKinoSaal.anzahlPlaetze = new KinoSaal.AnzahlPlaetze(30);
newKino.kinoSaele = Set.of(newKinoSaal);
KinoTO mappedKino = KinoKinoSaal2KinoKinoSaalTOMapper.mapKino(newKino);
VorfuehrungTO changedVorfuehrung = new VorfuehrungTO(vorfuehrung.id(), vorfuehrung.version(), vorfuehrung.zeit(),
vorfuehrung.film(), mappedKino.kinoSaele().iterator().next(), mappedKino.id());
// act
ticketService.aktualisiereVorfuehrung(changedVorfuehrung.id(), getRawOrNull(changedVorfuehrung.kinoSaal().anzahlPlaetze()));
Optional<Kontingent> changedKontingentOptional = kontingentDao.findByVorfuehrung(vorfuehrung.id());
List<Ticket> changedTickets = ticketService.findByBesucher(besucherId);
// assert
assertThat(changedKontingentOptional.get().getRestKontingentOnline().raw()).isEqualTo(30/3);
assertThat(changedTickets.size()).isEqualTo(10);
// ... but all tickets not gueltig anymore
assertThat(changedTickets.stream().filter(t -> getRawOrNull(t.gueltig)).collect(Collectors.toList())).isEmpty();
}
}

View file

@ -0,0 +1,69 @@
package de.accso.flexinale.ticketing.domain.model;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.domain.model.Kontingent;
import de.accso.flexinale.ticketing.domain.model.KontingentBereitsAusgeschoepftException;
import org.junit.jupiter.api.Test;
import static de.accso.flexinale.ticketing.domain.model.Ticket.VerkaufsKanal.KINOKASSE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class KontingentTest {
@Test
void testOnlineKontingentCalculationQuote33() {
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung();
Kontingent kontingent = TestDataBuilder.createKontingent(30, 33, vorfuehrung);
assertThat(kontingent.getRestKontingentOnline().raw()).isEqualTo(10);
assertThat(kontingent.getRestKontingentZentral().raw()).isEqualTo(10);
assertThat(kontingent.getRestKontingentKinokasse().raw()).isEqualTo(10);
}
@Test
void testOnlineKontingentCalculationQuote25() {
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung();
Kontingent kontingent = TestDataBuilder.createKontingent(30, 25, vorfuehrung);
assertThat(kontingent.getRestKontingentOnline().raw()).isEqualTo(8);
assertThat(kontingent.getRestKontingentZentral().raw()).isEqualTo(11);
assertThat(kontingent.getRestKontingentKinokasse().raw()).isEqualTo(11);
}
@Test
void testOnlineKontingentCalculationQuote100() {
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung();
Kontingent kontingent = TestDataBuilder.createKontingent(30, 100, vorfuehrung);
assertThat(kontingent.getRestKontingentOnline().raw()).isEqualTo(30);
assertThat(kontingent.getRestKontingentZentral().raw()).isEqualTo(0);
assertThat(kontingent.getRestKontingentKinokasse().raw()).isEqualTo(0);
}
@Test
void testOnlineKontingentCalculationQuote0() {
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung();
Kontingent kontingent = TestDataBuilder.createKontingent(29, 0, vorfuehrung);
assertThat(kontingent.getRestKontingentOnline().raw()).isEqualTo(0);
assertThat(kontingent.getRestKontingentZentral().raw()).isEqualTo(14);
assertThat(kontingent.getRestKontingentKinokasse().raw()).isEqualTo(15);
}
@Test
void testNotEnoughKontingent() {
Vorfuehrung vorfuehrung = TestDataBuilder.createVorfuehrung();
Kontingent kontingent = TestDataBuilder.createKontingent(20, 90, vorfuehrung);
assertThatThrownBy(() -> {
Kontingent reduziertesKontingent = kontingent.reduziereKontingent(KINOKASSE, 4);
})
.isInstanceOf(KontingentBereitsAusgeschoepftException.class);
assertThat(kontingent.getRestKontingentOnline().raw()).isEqualTo(18);
assertThat(kontingent.getRestKontingentKinokasse().raw()).isEqualTo(1);
assertThat(kontingent.getRestKontingentZentral().raw()).isEqualTo(1);
}
}

View file

@ -0,0 +1,165 @@
package de.accso.flexinale.ticketing.infrastructure.persistence;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.Versionable;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.Optional;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class TicketEntityVersioningAndOptimisticLockingTest {
@Autowired
private TicketDao ticketDao;
@Test
void saveTicketInitiallySetsInitialVersionFromUnknownToZero() {
// arrange
Film film = createFilm();
Kino kino = createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
BenutzerEntity benutzer = createBenutzerEntity();
Ticket newCreatedTicket = createTicket(film, vorfuehrung, benutzer);
// act
ticketDao.save(newCreatedTicket);
// assert
assertThat(newCreatedTicket.version).isEqualTo(Versionable.unknownVersion());
Optional<Ticket> searchedTicket = ticketDao.findById(newCreatedTicket.id());
assertThat(searchedTicket.isPresent()).isTrue();
assertThat(searchedTicket.get().version).isEqualTo(Versionable.initialVersion());
// cleanup
ticketDao.deleteById(newCreatedTicket.id());
// assert
assertThat(ticketDao.findById(newCreatedTicket.id())).isEmpty();
}
@Test
void saveTicketThenChangeAndSaveAgainIncreasesItsVersion() {
// arrange
Ticket.VerkaufsKanal initialVerkaufskanal = Ticket.VerkaufsKanal.ONLINE;
Ticket.VerkaufsKanal changeToVerkaufskanal = Ticket.VerkaufsKanal.ZENTRAL;
Film film = createFilm();
Kino kino = createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
BenutzerEntity benutzer = createBenutzerEntity();
Ticket newCreatedTicket = createTicket(film, vorfuehrung, benutzer);
newCreatedTicket.verkaufsKanal = initialVerkaufskanal;
// act - save first time
ticketDao.save(newCreatedTicket);
assertThat(newCreatedTicket.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Ticket> searched1stTimeTicket = ticketDao.findById(newCreatedTicket.id());
assertThat(searched1stTimeTicket.isPresent()).isTrue();
// assert that version has been updated
Ticket ticketToUpdateAndSaveAgain = searched1stTimeTicket.get();
assertThat(ticketToUpdateAndSaveAgain.version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
ticketToUpdateAndSaveAgain.verkaufsKanal = changeToVerkaufskanal; // change value on the loaded entity
ticketDao.save(ticketToUpdateAndSaveAgain);
// act - load again from db
Optional<Ticket> searched2ndTimeTicket = ticketDao.findById(newCreatedTicket.id());
assertThat(searched2ndTimeTicket.isPresent()).isTrue();
Ticket ticketLoadedAfterChange = searched2ndTimeTicket.get();
assertThat(ticketLoadedAfterChange.version).isEqualTo(Versionable.Version.of(1)); // version increased after update
assertThat(ticketLoadedAfterChange.id).isEqualTo(newCreatedTicket.id);
assertThat(ticketLoadedAfterChange.filmId.equals(newCreatedTicket.filmId)).isTrue();
assertThat(ticketLoadedAfterChange.vorfuehrungId.equals(newCreatedTicket.vorfuehrungId)).isTrue();
assertThat(ticketLoadedAfterChange.besucherId.equals(newCreatedTicket.besucherId)).isTrue();
assertThat(ticketLoadedAfterChange.verkaufsKanal).isEqualTo(changeToVerkaufskanal);
// cleanup
ticketDao.deleteById(newCreatedTicket.id());
// assert
assertThat(ticketDao.findById(newCreatedTicket.id())).isEmpty();
}
@Test
void saveTicketThenChangeAndSaveAgainUsingOutdatedVersionIsAnError() {
// arrange
Ticket.VerkaufsKanal initialVerkaufskanal = Ticket.VerkaufsKanal.ONLINE;
Ticket.VerkaufsKanal changeToVerkaufskanal = Ticket.VerkaufsKanal.ZENTRAL;
Film film = createFilm();
Kino kino = createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
BenutzerEntity benutzer = createBenutzerEntity();
Ticket newCreatedTicket = createTicket(film, vorfuehrung, benutzer);
newCreatedTicket.verkaufsKanal = initialVerkaufskanal;
// act - save first time
ticketDao.save(newCreatedTicket);
assertThat(newCreatedTicket.version).isEqualTo(Versionable.unknownVersion());
// act - load from db and change
Optional<Ticket> searched1stTimeTicket = ticketDao.findById(newCreatedTicket.id());
assertThat(searched1stTimeTicket.isPresent()).isTrue();
// assert that version has been updated
assertThat(searched1stTimeTicket.get().version).isEqualTo(Versionable.initialVersion()); // version increased after initial create
// act - change and save again
newCreatedTicket.verkaufsKanal = changeToVerkaufskanal; // change value but not the version
// act
Throwable thrown = catchThrowable(() -> ticketDao.save(newCreatedTicket));
// assert
String expectedMessagePart =
"Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [de.accso.flexinale.ticketing.infrastructure.persistence.TicketEntity";
assertThat(thrown)
.isInstanceOf(OptimisticLockingFailureException.class)
.hasMessageContaining(expectedMessagePart);
// cleanup
ticketDao.deleteById(newCreatedTicket.id());
// assert
assertThat(ticketDao.findById(newCreatedTicket.id())).isEmpty();
}
}

View file

@ -0,0 +1,105 @@
package de.accso.flexinale.ticketing.infrastructure.persistence;
import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.Test;
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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class TicketPersistenceTest {
@Autowired
private TicketDao ticketDao;
@Autowired
private VorfuehrungDao vorfuehrungDao;
@Autowired
private KinoDao kinoDao;
@Autowired
private FilmDao filmDao;
@Test
void saveAndDeleteTicket() {
// arrange
BenutzerEntity benutzer = createBenutzerEntity();
Film film = createFilm();
Kino kino = TestDataBuilder.createKinoWithKinosaele(100);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
Ticket ticket = createTicket(film, vorfuehrung, benutzer);
// act
ticketDao.save(ticket);
// assert
Optional<Ticket> optionalSearchedTicket = ticketDao.findById(ticket.id());
assertThat(optionalSearchedTicket.isPresent()).isTrue();
Ticket searchedTicket = optionalSearchedTicket.get();
assertThat(searchedTicket.equalsByContent(ticket)).isTrue();
// cleanup
ticketDao.deleteById(ticket.id());
// assert
assertThat(ticketDao.findById(ticket.id())).isEmpty();
}
@Test
void saveTicketAndFindByBenutzerOrderByZeitAndDelete() {
// arrange
LocalDateTime now = LocalDateTime.now();
BenutzerEntity benutzer = createBenutzerEntity();
Film film = createFilm();
filmDao.save(film);
Kino kino = createKinoWithKinosaele();
kinoDao.save(kino);
KinoSaal kinoSaal = kino.kinoSaele.iterator().next();
Vorfuehrung vorfuehrung1 = createVorfuehrung(now, film, kinoSaal);
Vorfuehrung vorfuehrung2 = createVorfuehrung(now.plusDays(1), film, kinoSaal);
vorfuehrungDao.save(vorfuehrung1);
vorfuehrungDao.save(vorfuehrung2);
Ticket ticket1 = createTicket(film, vorfuehrung1, benutzer);
Ticket ticket2 = createTicket(film, vorfuehrung2, benutzer);
// act
ticketDao.save(ticket1);
ticketDao.save(ticket2);
List<Ticket> tickets = ticketDao.findByBesucher(Identifiable.Id.of(benutzer.id));
assertThat(tickets).hasSize(2);
}
}

View file

@ -0,0 +1,39 @@
application.title=FLEXinale as Distributed Services, Test
application.version=test
spring.banner.location=classpath:/flexinale-banner.txt
#########################################################################
# For endpoint /version
#########################################################################
build.version=@pom.version@
build.date=@maven.build.timestamp@
#########################################################################
# Persistence
#########################################################################
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/distributed-test
spring.datasource.name=flexinale
spring.datasource.username=flexinale
spring.datasource.password=flexinale
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database=postgresql
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.generate-ddl=true
# spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
server.port=9093
#########################################################################
# Web
#########################################################################
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
server.error.path=/error
#########################################################################
# flexinale properties
#########################################################################
# Quote for online kontingent in percent
de.accso.flexinale.kontingent.quote.online=33
# time in minutes
de.accso.flexinale.vorfuehrung.min-zeit-zwischen-vorfuehrungen-in-minuten=30

View file

@ -0,0 +1,20 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYYMMdd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.orm.jpa" level="INFO"/>
<logger name="org.springframework.boot.autoconfigure.domain.EntityScan" level="INFO"/>
<logger name="org.apache.kafka" level="WARN"/>
<logger name="org.apache.kafka.clients.admin.AdminClient" level="INFO"/>
<logger name="org.apache.kafka.clients.consumer.ConsumerConfig" level="INFO"/>
<logger name="org.apache.kafka.clients.producer.ProducerConfig" level="INFO"/>
<logger name="de.accso" level="INFO"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>