1
0

refactoring for implicit creation of dependend hosting-assets (#108)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/108
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-09-26 10:51:27 +02:00
parent d949604d70
commit cb4aecb9c8
47 changed files with 474 additions and 139 deletions

View File

@@ -1,17 +1,20 @@
package net.hostsharing.hsadminng.hs.booking.item;
import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRealEntity;
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRealRepository;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StrictMapper;
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
@@ -28,13 +31,14 @@ import java.util.UUID;
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
import static org.hamcrest.Matchers.matchesRegex;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HsBookingItemController.class)
@Import(Mapper.class)
@Import({StrictMapper.class, JsonObjectMapperConfiguration.class})
@RunWith(SpringRunner.class)
class HsBookingItemControllerRestTest {
@@ -44,8 +48,12 @@ class HsBookingItemControllerRestTest {
@MockBean
Context contextMock;
@Mock
EntityManager em;
@Autowired
@SuppressWarnings("unused") // not used in test, but in controller class
StrictMapper mapper;
@MockBean
EntityManagerWrapper em;
@MockBean
EntityManagerFactory emf;
@@ -56,6 +64,16 @@ class HsBookingItemControllerRestTest {
@MockBean
HsBookingItemRbacRepository rbacBookingItemRepo;
@TestConfiguration
public static class TestConfig {
@Bean
public EntityManager entityManager() {
return mock(EntityManager.class);
}
}
@BeforeEach
void init() {
when(emf.createEntityManager()).thenReturn(em);

View File

@@ -35,7 +35,8 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", "example.org")
entry("domainName", "example.org"),
entry("targetUnixUser", "xyz00")
))
.build();
@@ -55,6 +56,7 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", "example.org"),
entry("targetUnixUser", "xyz00"),
entry("verificationCode", "1234-5678-9100")
))
.build();
@@ -73,7 +75,8 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", right(TOO_LONG_DOMAIN_NAME, 253))
entry("domainName", right(TOO_LONG_DOMAIN_NAME, 253)),
entry("targetUnixUser", "xyz00")
))
.build();
@@ -91,7 +94,8 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", right(TOO_LONG_DOMAIN_NAME, 254))
entry("domainName", right(TOO_LONG_DOMAIN_NAME, 254)),
entry("targetUnixUser", "xyz00")
))
.build();
@@ -102,6 +106,44 @@ class HsDomainSetupBookingItemValidatorUnitTest {
assertThat(result).contains("'D-12345:Test-Project:Test-Domain.resources.domainName' length is expected to be at max 253 but length of 'dfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.asdfghijklmnopqrstuvwxyz0123456789.example.org' is 254");
}
@Test
void acceptsValidUnixUser() {
final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder()
.type(DOMAIN_SETUP)
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", "example.com"),
entry("targetUnixUser", "xyz00-test")
))
.build();
// when
final var result = HsBookingItemEntityValidatorRegistry.doValidate(em, domainSetupBookingItemEntity);
// then
assertThat(result).isEmpty();
}
@Test
void rejectsInvalidUnixUser() {
final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder()
.type(DOMAIN_SETUP)
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", "example.com"),
entry("targetUnixUser", "xyz00test")
))
.build();
// when
final var result = HsBookingItemEntityValidatorRegistry.doValidate(em, domainSetupBookingItemEntity);
// then
assertThat(result).contains("'D-12345:Test-Project:Test-Domain.resources.targetUnixUser' = 'xyz00test' is not a valid unix-user name");
}
@ParameterizedTest
@ValueSource(strings = {
"de", "com", "net", "org", "actually-any-top-level-domain",
@@ -123,7 +165,8 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", secondLevelRegistrarDomain)
entry("domainName", secondLevelRegistrarDomain),
entry("targetUnixUser", "xyz00")
))
.build();
@@ -148,7 +191,8 @@ class HsDomainSetupBookingItemValidatorUnitTest {
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", secondLevelRegistrarDomain)
entry("domainName", secondLevelRegistrarDomain),
entry("targetUnixUser", "xyz00")
))
.build();
@@ -170,6 +214,7 @@ class HsDomainSetupBookingItemValidatorUnitTest {
// then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=string, propertyName=domainName, matchesRegEx=[^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,12}], matchesRegExDescription=is not a (non-top-level) fully qualified domain name, notMatchesRegEx=[[^.]+, (co|org|gov|ac|sch)\\.uk, (com|net|org|edu|gov|asn|id)\\.au, (co|ne|or|ac|go)\\.jp, (com|net|org|gov|edu|ac)\\.cn, (com|net|org|gov|edu|mil|art)\\.br, (co|net|org|gen|firm|ind)\\.in, (com|net|org|gob|edu)\\.mx, (gov|edu)\\.it, (co|net|org|govt|ac|school|geek|kiwi)\\.nz, (co|ne|or|go|re|pe)\\.kr], notMatchesRegExDescription=is a forbidden registrar-level domain name, maxLength=253, required=true, writeOnce=true}",
"{type=string, propertyName=targetUnixUser, matchesRegEx=[^[a-z][a-z0-9]{2}[0-9]{2}$|^[a-z][a-z0-9]{2}[0-9]{2}-[a-z0-9\\._-]+$], matchesRegExDescription=is not a valid unix-user name, maxLength=253, required=true, writeOnce=true}",
"{type=string, propertyName=verificationCode, minLength=12, maxLength=64, computed=IN_INIT}");
}
}

View File

@@ -9,7 +9,7 @@ import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealRepository;
import net.hostsharing.hsadminng.mapper.Array;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -52,7 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HsHostingAssetController.class)
@Import({Mapper.class, JsonObjectMapperConfiguration.class})
@Import({ StandardMapper.class, JsonObjectMapperConfiguration.class})
@RunWith(SpringRunner.class)
public class HsHostingAssetControllerRestTest {
@@ -63,10 +63,11 @@ public class HsHostingAssetControllerRestTest {
Context contextMock;
@Autowired
Mapper mapper;
@SuppressWarnings("unused") // not used in test, but in controller class
StandardMapper mapper;
@MockBean
private EntityManagerWrapper em;
EntityManagerWrapper em;
@MockBean
EntityManagerFactory emf;
@@ -90,6 +91,7 @@ public class HsHostingAssetControllerRestTest {
}
}
enum ListTestCases {
CLOUD_SERVER(
List.of(

View File

@@ -42,7 +42,8 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
.project(project)
.type(HsBookingItemType.DOMAIN_SETUP)
.resources(new HashMap<>(ofEntries(
entry("domainName", domainName)
entry("domainName", domainName),
entry("targetUnixUser", "xyz00")
))));
HsBookingItemEntityValidatorRegistry.forType(HsBookingItemType.DOMAIN_SETUP).prepareProperties(null, bookingItem);
return HsHostingAssetRbacEntity.builder()

View File

@@ -1680,13 +1680,19 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
final var relatedProject = domainSetup.getSubHostingAssets().stream()
.map(ha -> ha.getAssignedToAsset() != null ? ha.getAssignedToAsset().getRelatedProject() : null)
.findAny().orElseThrow();
final var targetUnixUser = domainSetup.getSubHostingAssets().stream()
.filter(subAsset -> subAsset.getType() == DOMAIN_HTTP_SETUP)
.map(domainHttpSetup -> domainHttpSetup.getAssignedToAsset().getIdentifier())
.findAny().orElse(null);
final var bookingItem = HsBookingItemRealEntity.builder()
.type(HsBookingItemType.DOMAIN_SETUP)
.caption("BI " + domainSetup.getIdentifier())
.project((HsBookingProjectRealEntity) relatedProject)
//.validity(toPostgresDateRange(created, cancelled))
.resources(Map.ofEntries(
entry("domainName", domainSetup.getIdentifier())))
entry("domainName", domainSetup.getIdentifier()),
entry("targetUnixUser", targetUnixUser)
))
.build();
domainSetup.setBookingItem(bookingItem);
bookingItems.put(nextAvailableBookingItemId(), bookingItem);

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.hs.office.bankaccount;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,7 +25,7 @@ class HsOfficeBankAccountControllerRestTest {
Context contextMock;
@MockBean
Mapper mapper;
StandardMapper mapper;
@MockBean
HsOfficeBankAccountRepository bankAccountRepo;

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.hs.office.coopassets;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.rbac.test.JsonBuilder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -30,7 +30,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
Context contextMock;
@MockBean
Mapper mapper;
StandardMapper mapper;
@MockBean
HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo;

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.hs.office.coopshares;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.rbac.test.JsonBuilder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -30,7 +30,7 @@ class HsOfficeCoopSharesTransactionControllerRestTest {
Context contextMock;
@MockBean
Mapper mapper;
StandardMapper mapper;
@MockBean
HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo;

View File

@@ -433,7 +433,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
.post("http://localhost/api/hs/office/debitors")
.then().log().all().assertThat()
.statusCode(400)
.body("message", is("ERROR: [400] Unable to find RealRelation by uuid: 00000000-0000-0000-0000-000000000000"));
.body("message", is("ERROR: [400] Unable to find RealRelation by debitorRelUuid: 00000000-0000-0000-0000-000000000000"));
// @formatter:on
}
}

View File

@@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.membership;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionRepository;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -32,7 +32,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HsOfficeMembershipController.class)
@Import(Mapper.class)
@Import(StandardMapper.class)
public class HsOfficeMembershipControllerRestTest {
@Autowired
@@ -115,7 +115,7 @@ public class HsOfficeMembershipControllerRestTest {
.andExpect(status().is4xxClientError())
.andExpect(jsonPath("statusCode", is(400)))
.andExpect(jsonPath("statusPhrase", is("Bad Request")))
.andExpect(jsonPath("message", is("ERROR: [400] Unable to find Partner by uuid: " + givenPartnerUuid)));
.andExpect(jsonPath("message", is("ERROR: [400] Unable to find Partner by partner.uuid: " + givenPartnerUuid)));
}
@ParameterizedTest

View File

@@ -4,7 +4,7 @@ import io.hypersistence.utils.hibernate.type.range.Range;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipStatusResource;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInstance;
@@ -40,7 +40,7 @@ class HsOfficeMembershipEntityPatcherUnitTest extends PatchUnitTestBase<
@Mock
private EntityManager em;
private Mapper mapper = new Mapper();
private StandardMapper mapper = new StandardMapper();
@BeforeEach
void initMocks() {

View File

@@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRbacEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -36,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HsOfficePartnerController.class)
@Import(Mapper.class)
@Import(StandardMapper.class)
class HsOfficePartnerControllerRestTest {
static final UUID GIVEN_MANDANTE_UUID = UUID.randomUUID();

View File

@@ -195,7 +195,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
.post("http://localhost/api/hs/office/sepamandates")
.then().log().all().assertThat()
.statusCode(400)
.body("message", is("ERROR: [400] Unable to find BankAccount by uuid: 00000000-0000-0000-0000-000000000000"));
.body("message", is("ERROR: [400] Unable to find BankAccount with uuid 00000000-0000-0000-0000-000000000000"));
// @formatter:on
}
@@ -225,7 +225,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
.post("http://localhost/api/hs/office/sepamandates")
.then().log().all().assertThat()
.statusCode(400)
.body("message", is("ERROR: [400] Unable to find Debitor by uuid: 00000000-0000-0000-0000-000000000000"));
.body("message", is("ERROR: [400] Unable to find Debitor with uuid 00000000-0000-0000-0000-000000000000"));
// @formatter:on
}
}

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.rbac.context;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.mapper.Array;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import org.junit.jupiter.api.Test;
@@ -17,7 +17,7 @@ import jakarta.servlet.http.HttpServletRequest;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { Context.class, JpaAttempt.class, Mapper.class })
@ComponentScan(basePackageClasses = { Context.class, JpaAttempt.class, StandardMapper.class })
@DirtiesContext
class ContextIntegrationTests {

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.rbac.role;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
@@ -30,7 +30,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(RbacRoleController.class)
@Import(Mapper.class)
@Import(StandardMapper.class)
@RunWith(SpringRunner.class)
class RbacRoleControllerRestTest {

View File

@@ -1,7 +1,7 @@
package net.hostsharing.hsadminng.rbac.subject;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
@@ -31,7 +31,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(RbacSubjectController.class)
@Import(Mapper.class)
@Import(StandardMapper.class)
@RunWith(SpringRunner.class)
class RbacSubjectControllerRestTest {

View File

@@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.rbac.test;
import lombok.*;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.StandardMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -27,7 +27,7 @@ class MapperUnitTest {
EntityManager em;
@InjectMocks
Mapper mapper;
StandardMapper mapper;
final UUID GIVEN_UUID = UUID.randomUUID();
@@ -50,7 +50,7 @@ class MapperUnitTest {
@Test
void mapsBeanWithExistingSubEntity() {
final SourceBean givenSource = SourceBean.builder().a("1234").b("Text").s1(new SubSourceBean1(GIVEN_UUID)).build();
when(em.find(SubTargetBean1.class, GIVEN_UUID)).thenReturn(new SubTargetBean1(GIVEN_UUID, "xxx"));
when(em.getReference(SubTargetBean1.class, GIVEN_UUID)).thenReturn(new SubTargetBean1(GIVEN_UUID, "xxx"));
final var result = mapper.map(givenSource, TargetBean.class);
assertThat(result).usingRecursiveComparison().isEqualTo(
@@ -81,27 +81,27 @@ class MapperUnitTest {
@Test
void mapsBeanWithSubEntityNotFound() {
final SourceBean givenSource = SourceBean.builder().a("1234").b("Text").s1(new SubSourceBean1(GIVEN_UUID)).build();
when(em.find(SubTargetBean1.class, GIVEN_UUID)).thenReturn(null);
when(em.getReference(SubTargetBean1.class, GIVEN_UUID)).thenReturn(null);
final var exception = catchThrowable(() ->
mapper.map(givenSource, TargetBean.class)
);
assertThat(exception).isInstanceOf(ValidationException.class)
.hasMessage("Unable to find SubTargetBean1 by uuid: " + GIVEN_UUID);
.hasMessage("Unable to find SubTargetBean1 by s1.uuid: " + GIVEN_UUID);
}
@Test
void mapsBeanWithSubEntityNotFoundAndDisplayName() {
final SourceBean givenSource = SourceBean.builder().a("1234").b("Text").s2(new SubSourceBean2(GIVEN_UUID)).build();
when(em.find(SubTargetBean2.class, GIVEN_UUID)).thenReturn(null);
when(em.getReference(SubTargetBean2.class, GIVEN_UUID)).thenReturn(null);
final var exception = catchThrowable(() ->
mapper.map(givenSource, TargetBean.class)
);
assertThat(exception).isInstanceOf(ValidationException.class)
.hasMessage("Unable to find SomeDisplayName by uuid: " + GIVEN_UUID);
.hasMessage("Unable to find SomeDisplayName by s2.uuid: " + GIVEN_UUID);
}
@Test