added tests
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<groupId>com.pfefferminzia</groupId>
|
||||||
|
<artifactId>pet-insurance</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.release>25</maven.compiler.release>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<junit.jupiter.version>5.11.4</junit.jupiter.version>
|
||||||
|
<maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
|
||||||
|
<maven.surefire.plugin.version>3.5.2</maven.surefire.plugin.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven.compiler.plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<release>${maven.compiler.release}</release>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven.surefire.plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package com.pfefferminzia.petinsurance.calculations;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import com.pfefferminzia.petinsurance.animals.Animal;
|
||||||
|
import com.pfefferminzia.petinsurance.animals.Cat;
|
||||||
|
import com.pfefferminzia.petinsurance.animals.Dog;
|
||||||
|
import com.pfefferminzia.petinsurance.animals.SmallAnimal;
|
||||||
|
import com.pfefferminzia.petinsurance.exception.InvalidInsuranceContractException;
|
||||||
|
import com.pfefferminzia.petinsurance.tariffs.TariffConfiguration;
|
||||||
|
import com.pfefferminzia.petinsurance.tariffs.TariffLoader;
|
||||||
|
|
||||||
|
class CalculationsTest {
|
||||||
|
private static Calculations calculationsEngine;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setUp() {
|
||||||
|
TariffConfiguration tariffConfig = TariffLoader.loadFromFile();
|
||||||
|
calculationsEngine = new Calculations(tariffConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream<Arguments> dogBreedPremiumCases() {
|
||||||
|
return Stream.of(Arguments.of("Husky", new BigDecimal("3500"), new BigDecimal("980")),
|
||||||
|
Arguments.of("Dackel", new BigDecimal("3500"), new BigDecimal("882")),
|
||||||
|
Arguments.of("Bernhardiner", new BigDecimal("3500"), new BigDecimal("1078")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("dogBreedPremiumCases")
|
||||||
|
void shouldCalculateCorrectlyForDogSevenYearsAndPremiumTariff(String breed,
|
||||||
|
BigDecimal expectedSum, BigDecimal expectedPremium) {
|
||||||
|
|
||||||
|
Animal dog = new Dog(LocalDate.of(2019, 8, 1), breed);
|
||||||
|
InsuranceContract contract =
|
||||||
|
new InsuranceContract(dog, LocalDate.of(2026, 8, 1), "PREMIUM");
|
||||||
|
|
||||||
|
CalculationResult result =
|
||||||
|
calculationsEngine.calculateInsuranceSumAndYearlyPremium(contract);
|
||||||
|
|
||||||
|
assertBigDecimalEquals(expectedSum, result.insuranceSum());
|
||||||
|
assertBigDecimalEquals(expectedPremium, result.yearlyPremium());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCalculateCorrectlyForCatThreeYearsAndOptimalTariff() {
|
||||||
|
Animal cat = new Cat(LocalDate.of(2023, 8, 1));
|
||||||
|
InsuranceContract contract =
|
||||||
|
new InsuranceContract(cat, LocalDate.of(2026, 8, 1), "OPTIMAL");
|
||||||
|
|
||||||
|
CalculationResult result =
|
||||||
|
calculationsEngine.calculateInsuranceSumAndYearlyPremium(contract);
|
||||||
|
|
||||||
|
assertBigDecimalEquals(new BigDecimal("2400"), result.insuranceSum());
|
||||||
|
assertBigDecimalEquals(new BigDecimal("600"), result.yearlyPremium());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCalculateCorrectlyForSmallAnimalOneYearAndKompaktTariff() {
|
||||||
|
Animal smallAnimal = new SmallAnimal(LocalDate.of(2025, 8, 1));
|
||||||
|
InsuranceContract contract =
|
||||||
|
new InsuranceContract(smallAnimal, LocalDate.of(2026, 8, 1), "KOMPAKT");
|
||||||
|
|
||||||
|
CalculationResult result =
|
||||||
|
calculationsEngine.calculateInsuranceSumAndYearlyPremium(contract);
|
||||||
|
|
||||||
|
assertBigDecimalEquals(new BigDecimal("1000"), result.insuranceSum());
|
||||||
|
assertBigDecimalEquals(new BigDecimal("200"), result.yearlyPremium());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream<Arguments> ageBracketCases() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(2, new BigDecimal("200")), // exactly at ≤2 boundary → factor 0.20
|
||||||
|
Arguments.of(3, new BigDecimal("250")), // one above ≤2 boundary → factor 0.25
|
||||||
|
Arguments.of(5, new BigDecimal("250")), // exactly at ≤5 boundary → factor 0.25
|
||||||
|
Arguments.of(6, new BigDecimal("280")), // one above ≤5 boundary → factor 0.28
|
||||||
|
Arguments.of(7, new BigDecimal("280")), // exactly at ≤7 boundary → factor 0.28
|
||||||
|
Arguments.of(8, new BigDecimal("300")) // one above ≤7 boundary → factor 0.30
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "age {0} → premium {1}")
|
||||||
|
@MethodSource("ageBracketCases")
|
||||||
|
void shouldApplyCorrectAgeFactorAtEachBracketBoundary(int age, BigDecimal expectedPremium) {
|
||||||
|
LocalDate startDate = LocalDate.of(2026, 8, 1);
|
||||||
|
Animal animal = new SmallAnimal(startDate.minusYears(age));
|
||||||
|
InsuranceContract contract = new InsuranceContract(animal, startDate, "KOMPAKT");
|
||||||
|
|
||||||
|
CalculationResult result =
|
||||||
|
calculationsEngine.calculateInsuranceSumAndYearlyPremium(contract);
|
||||||
|
|
||||||
|
assertBigDecimalEquals(expectedPremium, result.yearlyPremium());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowExceptionWhenPremiumTariffIsSelectedBeforeJulyFirst() {
|
||||||
|
Animal dog = new Dog(LocalDate.of(2019, 8, 1), "Schäferhund");
|
||||||
|
InsuranceContract contract =
|
||||||
|
new InsuranceContract(dog, LocalDate.of(2026, 2, 1), "PREMIUM");
|
||||||
|
|
||||||
|
assertThrows(IllegalStateException.class,
|
||||||
|
() -> calculationsEngine.calculateInsuranceSumAndYearlyPremium(contract));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReportViolationWhenAnimalIsNull() {
|
||||||
|
LocalDate insuranceStart = LocalDate.of(2026, 8, 1);
|
||||||
|
|
||||||
|
InvalidInsuranceContractException ex = assertThrows(InvalidInsuranceContractException.class,
|
||||||
|
() -> new InsuranceContract(null, insuranceStart, "KOMPAKT"));
|
||||||
|
|
||||||
|
assertEquals(List.of("Animal darf nicht leer sein"), ex.getViolations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReportViolationWhenTariffNameIsNull() {
|
||||||
|
Animal animal = new Cat(LocalDate.of(2023, 8, 1));
|
||||||
|
LocalDate insuranceStart = LocalDate.of(2026, 8, 1);
|
||||||
|
|
||||||
|
|
||||||
|
InvalidInsuranceContractException ex = assertThrows(InvalidInsuranceContractException.class,
|
||||||
|
() -> new InsuranceContract(animal, insuranceStart, null));
|
||||||
|
|
||||||
|
assertEquals(List.of("Tarif darf nicht leer sein"), ex.getViolations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReportViolationWhenInsuranceStartDateIsNull() {
|
||||||
|
Animal animal = new Cat(LocalDate.of(2023, 8, 1));
|
||||||
|
|
||||||
|
InvalidInsuranceContractException ex = assertThrows(InvalidInsuranceContractException.class,
|
||||||
|
() -> new InsuranceContract(animal, null, "KOMPAKT"));
|
||||||
|
|
||||||
|
assertEquals(List.of("Versicherungsstart darf nicht leer sein"), ex.getViolations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReportViolationWhenBirthdayIsAfterContractStart() {
|
||||||
|
Animal animal = new Cat(LocalDate.of(2026, 8, 1));
|
||||||
|
LocalDate insuranceStart = LocalDate.of(2026, 2, 1);
|
||||||
|
|
||||||
|
InvalidInsuranceContractException ex = assertThrows(InvalidInsuranceContractException.class,
|
||||||
|
() -> new InsuranceContract(animal, insuranceStart, "KOMPAKT"));
|
||||||
|
|
||||||
|
assertEquals(List.of("Start der Versicherung kann nicht vor dem Geburtstag sein."),
|
||||||
|
ex.getViolations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCollectAllViolationsWhenMultipleFieldsAreInvalid() {
|
||||||
|
InvalidInsuranceContractException ex = assertThrows(InvalidInsuranceContractException.class,
|
||||||
|
() -> new InsuranceContract(null, null, null));
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
List.of("Animal darf nicht leer sein", "Tarif darf nicht leer sein",
|
||||||
|
"Versicherungsstart darf nicht leer sein"),
|
||||||
|
ex.getViolations());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertBigDecimalEquals(BigDecimal expected, BigDecimal actual) {
|
||||||
|
if (expected.compareTo(actual) != 0) {
|
||||||
|
fail(String.format("Expected: <%s> but is: <%s>", expected.toPlainString(),
|
||||||
|
actual.toPlainString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
# Animal base insurance sums: species=baseSum
|
||||||
|
baseSum.DOG=2500.00
|
||||||
|
baseSum.CAT=2000.00
|
||||||
|
baseSum.SMALLANIMAL=1000.00
|
||||||
|
|
||||||
|
# Tariffs: name=factor,availableFromDate
|
||||||
|
tariffs.KOMPAKT=1.0,1970-01-01
|
||||||
|
tariffs.OPTIMAL=1.2,1970-01-01
|
||||||
|
tariffs.PREMIUM=1.4,2026-07-01
|
||||||
|
|
||||||
|
# Age tariffs factor: age=factor
|
||||||
|
age.2=0.20
|
||||||
|
age.5=0.25
|
||||||
|
age.7=0.28
|
||||||
|
elderlyFactor=0.30
|
||||||
|
|
||||||
|
# Dog breed premium factor: breed=factor
|
||||||
|
breed.DACKEL=-0.1
|
||||||
|
breed.BERNHARDINER=0.1
|
||||||
Reference in New Issue
Block a user