experimental CustomerRepositoryIntegrationTest with Given/When/Then classes

This commit is contained in:
Michael Hoennig 2022-08-01 12:53:09 +02:00
parent 27c5699c36
commit f58a68d1cc

View File

@ -1,26 +1,26 @@
package net.hostsharing.hsadminng.hscustomer; package net.hostsharing.hsadminng.hscustomer;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.NestedRuntimeException;
import org.springframework.orm.jpa.JpaSystemException; import org.springframework.orm.jpa.JpaSystemException;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
@DataJpaTest @DataJpaTest
@ComponentScan(basePackageClasses = { Context.class, CustomerRepository.class }) @ComponentScan(basePackageClasses = { Context.class, CustomerRepository.class })
class CustomerRepositoryIntegrationTest { class CustomerRepositoryIntegrationTest {
final static String adminUser = "mike@hostsharing.net";
final static String customerAaa = "admin@aaa.example.com";
@Autowired @Autowired
Context context; Context context;
@ -29,127 +29,154 @@ class CustomerRepositoryIntegrationTest {
@Autowired EntityManager em; @Autowired EntityManager em;
@Test @Nested
@Transactional class FindAll {
void hostsharingAdminWithoutAssumedRoleCanViewAllCustomers() {
// given
context.setCurrentUser(adminUser);
// when private final Given given = new Given();
final var actual = customerRepository.findAll(); private When<List<CustomerEntity>> when;
private final Then then = new Then();
// then @Test
public void hostsharingAdminWithoutAssumedRoleCanViewAllCustomers() {
given.currentUser("mike@hostsharing.net");
assertThat(actual).hasSize(3) when(() -> customerRepository.findAll());
.extracting(CustomerEntity::getPrefix)
.containsExactlyInAnyOrder("aaa", "aab", "aac"); then.exactlyTheseCustomersAreReturned("aaa", "aab", "aac");
}
@Test
public void hostsharingAdminWithAssumedHostsharingAdminRoleCanViewAllCustomers() {
given.currentUser("mike@hostsharing.net").
and().assumedRoles("global#hostsharing.admin");
when(() -> customerRepository.findAll());
then.exactlyTheseCustomersAreReturned("aaa", "aab", "aac");
}
@Test
public void customerAdminWithoutAssumedRoleCanViewOnlyItsOwnCustomer() {
given.currentUser("admin@aaa.example.com");
when(() -> customerRepository.findAll());
then.exactlyTheseCustomersAreReturned("aaa");
}
@Test
public void customerAdminWithAssumedOwnedPackageAdminRoleCanViewOnlyItsOwnCustomer() {
given.currentUser("admin@aaa.example.com").
and().assumedRoles("package#aaa00.admin");
when(() -> customerRepository.findAll());
then.exactlyTheseCustomersAreReturned("aaa");
}
@Test
public void customerAdmin_withAssumedAlienPackageAdminRole_cannotViewAnyCustomer() {
given.currentUser("admin@aaa.example.com").
and().assumedRoles("package#aab00.admin");
when(() -> customerRepository.findAll());
then.expectJpaSystemExceptionHasBeenThrown().
and()
.expectRootCauseMessageMatches(
".* user admin@aaa.example.com .* has no permission to assume role package#aab00#admin .*");
}
@Test
void unknownUser_withoutAssumedRole_cannotViewAnyCustomers() {
given.currentUser("unknown@example.org");
when(() -> customerRepository.findAll());
then.expectJpaSystemExceptionHasBeenThrown().
and().expectRootCauseMessageMatches(".* user unknown@example.org does not exist.*");
}
@Test
@Transactional
void unknownUserWithAssumedCustomerRoleCannotViewAnyCustomers() {
given.currentUser("unknown@example.org").
and().assumedRoles("customer#aaa.admin");
when(() -> customerRepository.findAll());
then.expectJpaSystemExceptionHasBeenThrown().
and().expectRootCauseMessageMatches(".* user unknown@example.org does not exist.*");
}
void when(final Supplier<List<CustomerEntity>> code) {
try {
when = new When<>(code.get());
} catch (final NestedRuntimeException exc) {
when = new When<>(exc);
}
}
private class Then {
Then and() {
return this;
}
void exactlyTheseCustomersAreReturned(final String... customerPrefixes) {
assertThat(when.actualResult)
.hasSize(customerPrefixes.length)
.extracting(CustomerEntity::getPrefix)
.containsExactlyInAnyOrder(customerPrefixes);
}
Then expectJpaSystemExceptionHasBeenThrown() {
assertThat(when.actualException).isInstanceOf(JpaSystemException.class);
return this;
}
void expectRootCauseMessageMatches(final String expectedMessage) {
assertThat(firstRootCauseMessageLineOf(when.actualException)).matches(expectedMessage);
}
}
} }
@Test private String firstRootCauseMessageLineOf(final NestedRuntimeException exception) {
@Transactional return Optional.ofNullable(exception.getRootCause())
void hostsharingAdminWithAssumedHostsharingAdminRoleCanViewAllCustomers() {
// given
context.setCurrentUser(adminUser);
context.assumeRoles("global#hostsharing.admin");
// when
final var actual = customerRepository.findAll();
// then
assertThat(actual).hasSize(3)
.extracting(CustomerEntity::getPrefix)
.containsExactlyInAnyOrder("aaa", "aab", "aac");
}
@Test
@Transactional
void customerAdminWithoutAssumedRoleCanViewItsOwnCustomer() {
// given
context.setCurrentUser(customerAaa);
// when
final var actual = customerRepository.findAll();
// then
assertThat(actual).hasSize(1)
.extracting(CustomerEntity::getPrefix)
.containsExactly("aaa");
}
@Test
@Transactional
void customerAdminWithAssumedOwnedPackageAdminRoleCanViewItsOwnCustomer() {
// given
context.setCurrentUser(customerAaa);
context.assumeRoles("package#aaa00.admin");
// when
final var actual = customerRepository.findAll();
// then
assertThat(actual).hasSize(1)
.extracting(CustomerEntity::getPrefix)
.containsExactly("aaa");
}
@Test
@Transactional
void customerAdminWithAssumedAlienPackageAdminRoleCanViewItsOwnCustomer() {
// given
context.setCurrentUser(customerAaa);
context.assumeRoles("package#aab00.admin");
// when
final JpaSystemException thrown =
assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
// then
assertThat(firstRootCauseMessageLineOf(thrown)).matches(
".* user admin@aaa.example.com .* has no permission to assume role package#aab00#admin .*"
);
}
@Test
@Transactional
void unknownUserWithoutAssumedRoleCannotViewAnyCustomers() {
// given
context.setCurrentUser("unknown@example.org");
// when
final JpaSystemException thrown =
assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
// then
assertThat(firstRootCauseMessageLineOf(thrown)).matches(
".* user unknown@example.org does not exist.*"
);
}
@Test
@Transactional
void unknownUserWithAssumedRoleCannotViewAnyCustomers() {
// given
context.setCurrentUser("unknown@example.org");
assertThat(context.getCurrentUser()).isEqualTo("unknown@example.org");
context.assumeRoles("customer#aaa.admin");
// when
final JpaSystemException thrown =
assertThrows(JpaSystemException.class, () -> customerRepository.findAll());
// then
assertThat(firstRootCauseMessageLineOf(thrown)).matches(
".* user unknown@example.org does not exist.*"
);
}
private String firstRootCauseMessageLineOf(final JpaSystemException throwable) {
return Optional.ofNullable(throwable.getRootCause())
.map(Throwable::getMessage) .map(Throwable::getMessage)
.map( message -> message.split("\\r|\\n|\\r\\n", 0)[0]) .map(message -> message.split("\\r|\\n|\\r\\n", 0)[0])
.orElse(null); .orElse(null);
}
private class Given {
Given and() {
return this;
}
Given currentUser(final String currentUser) {
context.setCurrentUser(currentUser);
assertThat(context.getCurrentUser()).as("precondition").isEqualTo(currentUser);
return this;
}
void assumedRoles(final String assumedRoles) {
context.assumeRoles(assumedRoles);
assertThat(context.getAssumedRoles()).as("precondition").containsExactly(assumedRoles.split(";"));
}
}
private static class When<T> {
T actualResult;
NestedRuntimeException actualException;
When(final T actualResult) {
this.actualResult = actualResult;
}
When(final NestedRuntimeException exception) {
this.actualException = exception;
}
} }
} }