generalized AccessMappingsUnitTestBase

This commit is contained in:
Michael Hoennig 2019-04-28 12:02:01 +02:00
parent 0257c83fa5
commit 2cd92d4e2c
2 changed files with 117 additions and 50 deletions

View File

@ -1,14 +1,19 @@
package org.hostsharing.hsadminng.service.dto;
import org.apache.commons.lang3.RandomUtils;
import org.hostsharing.hsadminng.service.accessfilter.AccessFor;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.removeEnd;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -16,28 +21,71 @@ import static org.assertj.core.api.Assertions.assertThat;
* DTOs which implement AccessMapping are more like a DSL,
* this base class should be used to enforce its required structure.
*/
public abstract class AccessMappingsUnitTestBase {
public abstract class AccessMappingsUnitTestBase<D> {
protected AccessRightsMatcher initAccesFor(final Class<AssetDTO> dtoClass, final Role role) {
@Test
public void shouldConvertToString() {
final D sampleDto = createSampleDto(1234L);
final String dtoAsString = dtoToString(sampleDto);
assertThat(sampleDto.toString()).isEqualTo(dtoAsString);
}
@Test
@SuppressWarnings("all")
public void shouldImplementEqualsJustUsingClassAndId() {
final D dto = createSampleDto(1234L);
assertThat(dto.equals(dto)).isTrue();
final D dtoWithSameId = createRandomDto(1234L);
assertThat(dto.equals(dtoWithSameId)).isTrue();
final D dtoWithAnotherId = createRandomDto(RandomUtils.nextLong(2000, 9999));
assertThat(dtoWithAnotherId.equals(dtoWithSameId)).isFalse();
final D dtoWithoutId = createRandomDto(null);
assertThat(dto.equals(dtoWithoutId)).isFalse();
assertThat(dtoWithoutId.equals(dto)).isFalse();
assertThat(dto.equals(null)).isFalse();
assertThat(dto.equals("")).isFalse();
}
@Test
public void shouldImplementHashCodeJustUsingClassAndId() {
final long randomId = RandomUtils.nextLong();
final D dto = createSampleDto(randomId);
assertThat(dto.hashCode()).isEqualTo(Objects.hashCode(randomId));
final D dtoWithoutId = createRandomDto(null);
assertThat(dtoWithoutId.hashCode()).isEqualTo(Objects.hashCode(null));
}
protected abstract D createSampleDto(final Long id);
protected abstract D createRandomDto(final Long id);
protected AccessRightsMatcher initAccessFor(final Class<D> dtoClass, final Role role) {
return new AccessRightsMatcher(dtoClass, role, AccessFor::init);
}
protected AccessRightsMatcher updateAccesFor(final Class<AssetDTO> dtoClass, final Role role) {
protected AccessRightsMatcher updateAccessFor(final Class<D> dtoClass, final Role role) {
return new AccessRightsMatcher(dtoClass, role, AccessFor::update);
}
protected AccessRightsMatcher readAccesFor(final Class<AssetDTO> dtoClass, final Role role) {
protected AccessRightsMatcher readAccessFor(final Class<D> dtoClass, final Role role) {
return new AccessRightsMatcher(dtoClass, role, AccessFor::read);
}
// This class should have the same generics as the outer class, but then the
// method references (AccessFor::*) can't be resolved anymore by the Java compiler.
protected static class AccessRightsMatcher {
private final Class<AssetDTO> dtoClass;
private final Object dtoClass;
private final Role role;
private final String[] namesOfFieldsWithAccessForAnnotation;
private final String[] namesOfAccessibleFields;
AccessRightsMatcher(final Class<AssetDTO> dtoClass, final Role role, final Function<AccessFor, Role[]> access) {
AccessRightsMatcher(final Class dtoClass, final Role role, final Function<AccessFor, Role[]> access) {
this.dtoClass = dtoClass;
this.role = role;
@ -61,7 +109,7 @@ public abstract class AccessMappingsUnitTestBase {
}
private static Set<Field> determineFieldsWithAccessForAnnotation(final Class<AssetDTO> dtoClass) {
private static Set<Field> determineFieldsWithAccessForAnnotation(final Class<?> dtoClass) {
final Set<Field> fieldsWithAccessForAnnotation = new HashSet<>();
@ -83,4 +131,47 @@ public abstract class AccessMappingsUnitTestBase {
return false;
}
}
private String dtoToString(final D dto) {
final StringBuilder fieldValues = new StringBuilder();
boolean firstField = true;
for (Field field : dto.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(AccessFor.class)) {
firstField = appendCommaOptionally(fieldValues, firstField);
appendFieldName(fieldValues, field);
appendFieldValue(dto, fieldValues, field);
}
}
return dto.getClass().getSimpleName() + "{" + fieldValues + "}";
}
private void appendFieldValue(final D dto, final StringBuilder fieldValues, final Field field) {
final Object value = ReflectionUtil.getValue(dto, field);
final boolean inQuotes = isJHipsterToStringUsingQuotes(field);
if (inQuotes) {
fieldValues.append("'");
}
fieldValues.append(value);
if (inQuotes) {
fieldValues.append("'");
}
}
private void appendFieldName(final StringBuilder fieldValues, final Field field) {
fieldValues.append(removeEnd(field.getName(), "Id"));
fieldValues.append("=");
}
private boolean appendCommaOptionally(final StringBuilder fieldValues, boolean firstField) {
if (firstField) {
firstField = false;
} else {
fieldValues.append(", ");
}
return firstField;
}
private boolean isJHipsterToStringUsingQuotes(final Field field) {
return !Number.class.isAssignableFrom(field.getType()) && !Boolean.class.isAssignableFrom(field.getType());
}
}

View File

@ -9,82 +9,59 @@ import org.junit.Test;
import java.math.BigDecimal;
import java.time.LocalDate;
import static org.assertj.core.api.Assertions.assertThat;
public class AssetDTOUnitTest extends AccessMappingsUnitTestBase {
public class AssetDTOUnitTest extends AccessMappingsUnitTestBase<AssetDTO> {
@Test
public void shouldHaveProperAccessForAdmin() {
initAccesFor(AssetDTO.class, Role.ADMIN).shouldBeExactlyFor(
initAccessFor(AssetDTO.class, Role.ADMIN).shouldBeExactlyFor(
"membershipId", "documentDate", "amount", "action", "valueDate", "remark");
updateAccesFor(AssetDTO.class, Role.ADMIN).shouldBeExactlyFor("remark");
readAccesFor(AssetDTO.class, Role.ADMIN).shouldBeForAllFields();
updateAccessFor(AssetDTO.class, Role.ADMIN).shouldBeExactlyFor("remark");
readAccessFor(AssetDTO.class, Role.ADMIN).shouldBeForAllFields();
}
@Test
public void shouldHaveProperAccessForContractualContact() {
initAccesFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeForNothing();
updateAccesFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeForNothing();
readAccesFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeExactlyFor(
initAccessFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeForNothing();
updateAccessFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeForNothing();
readAccessFor(AssetDTO.class, Role.CONTRACTUAL_CONTACT).shouldBeExactlyFor(
"id", "membershipId", "documentDate", "amount", "action", "valueDate", "membershipDisplayLabel");
}
@Test
public void shouldHaveNoAccessForTechnicalContact() {
initAccesFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
updateAccesFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
readAccesFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
initAccessFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
updateAccessFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
readAccessFor(AssetDTO.class, Role.TECHNICAL_CONTACT).shouldBeForNothing();
}
@Test
public void shouldHaveNoAccessForNormalUsersWithinCustomerRealm() {
initAccesFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
updateAccesFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
readAccesFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
}
@Test
public void shouldConvertToString() {
final AssetDTO dto = createDto(1234L);
assertThat(dto.toString()).isEqualTo("AssetDTO{id=1234, documentDate='2000-12-07', valueDate='2000-12-18', action='PAYMENT', amount=512.01, remark='Some Remark', membership=888, membershipDisplayLabel='Some Membership'}");
}
@Test
public void shouldImplementEqualsJustUsingClassAndId() {
final AssetDTO dto = createDto(1234L);
assertThat(dto.equals(dto)).isTrue();
final AssetDTO dtoWithSameId = createRandomDto(1234L);
assertThat(dto.equals(dtoWithSameId)).isTrue();
final AssetDTO dtoWithAnotherId = createRandomDto(RandomUtils.nextLong(2000, 9999));
assertThat(dtoWithAnotherId.equals(dtoWithSameId)).isFalse();
final AssetDTO dtoWithoutId = createRandomDto(null);
assertThat(dto.equals(dtoWithoutId)).isFalse();
assertThat(dtoWithoutId.equals(dto)).isFalse();
assertThat(dto.equals(null)).isFalse();
assertThat(dto.equals("")).isFalse();
initAccessFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
updateAccessFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
readAccessFor(AssetDTO.class, Role.ANY_CUSTOMER_USER).shouldBeForNothing();
}
// --- only test fixture below ---
private AssetDTO createDto(final Long id) {
@Override
public AssetDTO createSampleDto(final Long id) {
final AssetDTO dto = new AssetDTO();
dto.setId(id);
dto.setDocumentDate(LocalDate.parse("2000-12-07"));
dto.setAmount(new BigDecimal("512.01"));
dto.setAction(AssetAction.PAYMENT);
dto.setRemark("Some Remark");
dto.setRemark(null);
dto.setValueDate(LocalDate.parse("2000-12-18"));
dto.setMembershipId(888L);
dto.setMembershipId(null);
dto.setMembershipDisplayLabel("Some Membership");
return dto;
}
private AssetDTO createRandomDto(final Long id) {
@Override
public AssetDTO createRandomDto(final Long id) {
final AssetDTO dto = new AssetDTO();
dto.setId(id);
final LocalDate randomDate = LocalDate.parse("2000-12-07").plusDays(RandomUtils.nextInt(1, 999));
@ -97,5 +74,4 @@ public class AssetDTOUnitTest extends AccessMappingsUnitTestBase {
dto.setMembershipDisplayLabel(RandomStringUtils.randomAlphabetic(20));
return dto;
}
}