AssetDTOUnitTest and Membership.displayLabel now with memberFrom/Until

This commit is contained in:
Michael Hoennig 2019-04-27 15:03:03 +02:00
parent 456a2f4811
commit 5edf97b230
6 changed files with 301 additions and 65 deletions

View File

@ -59,6 +59,11 @@ public class Asset implements Serializable {
return id; return id;
} }
public Asset id(Long id) {
this.id = id;
return this;
}
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }

View File

@ -2,7 +2,7 @@ package org.hostsharing.hsadminng.service.dto;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction; import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.service.AssetService; import org.hostsharing.hsadminng.service.AssetService;
import org.hostsharing.hsadminng.service.CustomerService; import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.*; import org.hostsharing.hsadminng.service.accessfilter.*;
import org.springframework.boot.jackson.JsonComponent; import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -40,13 +40,15 @@ public class AssetDTO implements Serializable, AccessMappings {
private BigDecimal amount; private BigDecimal amount;
@Size(max = 160) @Size(max = 160)
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = Role.ADMIN) @AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = Role.SUPPORTER)
private String remark; private String remark;
@ParentId(resolver = CustomerService.class) @ParentId(resolver = MembershipService.class)
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private Long membershipId; private Long membershipId;
// TODO: these init/update rights actually mean "ignore", we might want to express this in a better way
// background: there is no converter for any display label in DTOs to entity field values anyway
@AccessFor(init=Role.ANYBODY, update = Role.ANYBODY, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT}) @AccessFor(init=Role.ANYBODY, update = Role.ANYBODY, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
private String membershipDisplayLabel; private String membershipDisplayLabel;

View File

@ -19,8 +19,8 @@ public interface MembershipMapper extends EntityMapper<MembershipDTO, Membership
static String displayLabel(final Membership entity) { static String displayLabel(final Membership entity) {
final Customer customer = entity.getCustomer(); final Customer customer = entity.getCustomer();
return CustomerMapper.displayLabel(customer) + " " return CustomerMapper.displayLabel(customer) + " "
+ Objects.toString(entity.getAdmissionDocumentDate(), "") + " - " + Objects.toString(entity.getMemberFromDate(), "") + " - "
+ Objects.toString(entity.getCancellationDocumentDate(), "..."); + Objects.toString(entity.getMemberUntilDate(), "...");
} }
@Mapping(source = "customer.id", target = "customerId") @Mapping(source = "customer.id", target = "customerId")

View File

@ -1,11 +1,14 @@
package org.hostsharing.hsadminng.service.accessfilter; package org.hostsharing.hsadminng.service.accessfilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.List; import java.util.List;
public class JSonBuilder { public class JSonBuilder {
private StringBuilder json = new StringBuilder();
@SafeVarargs @SafeVarargs
public static String asJSon(final ImmutablePair<String, Object>... properties) { public static String asJSon(final ImmutablePair<String, Object>... properties) {
final StringBuilder json = new StringBuilder(); final StringBuilder json = new StringBuilder();
@ -15,14 +18,7 @@ public class JSonBuilder {
if (prop.right instanceof Number) { if (prop.right instanceof Number) {
json.append(prop.right); json.append(prop.right);
} else if (prop.right instanceof List) { } else if (prop.right instanceof List) {
json.append("["); json.append(toJSonArray(prop.right));
for ( int n = 0; n < ((List<Integer>)prop.right).size(); ++n ) {
if ( n > 0 ) {
json.append(",");
}
json.append(((List<Integer>)prop.right).get(n));
}
json.append("]");
} else { } else {
json.append(inQuotes(prop.right)); json.append(inQuotes(prop.right));
} }
@ -31,6 +27,50 @@ public class JSonBuilder {
return "{\n" + json.substring(0, json.length() - 2) + "\n}"; return "{\n" + json.substring(0, json.length() - 2) + "\n}";
} }
public JSonBuilder withFieldValue(String name, String value) {
json.append(inQuotes(name) + ":" + (value != null ? inQuotes(value) : "null") + ",");
return this;
}
public JSonBuilder withFieldValue(String name, Number value) {
json.append(inQuotes(name) + ":" + (value != null ? value : "null") + ",");
return this;
}
public JSonBuilder toJSonNullFieldDefinition(String name) {
json.append(inQuotes(name) + ":null,");
return this;
}
public JSonBuilder withFieldValueIfPresent(String name, String value) {
json.append(value != null ? inQuotes(name) + ":" + inQuotes(value) + "," : "");
return this;
}
public JSonBuilder withFieldValueIfPresent(String name, Number value) {
json.append(value != null ? inQuotes(name) + ":" + value + "," : "");
return this;
}
@Override
public String toString() {
return "{" + StringUtils.removeEnd(json.toString(), ",") + "}";
}
@SuppressWarnings("unchecked")
// currently just for the case of date values represented as arrays of integer
private static String toJSonArray(final Object value) {
final StringBuilder jsonArray = new StringBuilder("[");
for (int n = 0; n < ((List<Integer>) value).size(); ++n) {
if (n > 0) {
jsonArray.append(",");
}
jsonArray.append(((List<Integer>) value).get(n));
}
return jsonArray.toString() + "]";
}
private static String inQuotes(Object value) { private static String inQuotes(Object value) {
return value != null ? "\"" + value.toString() + "\"" : "null"; return value != null ? "\"" + value.toString() + "\"" : "null";
} }

View File

@ -0,0 +1,214 @@
package org.hostsharing.hsadminng.service.dto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.RandomUtils;
import org.hostsharing.hsadminng.domain.Asset;
import org.hostsharing.hsadminng.domain.Customer;
import org.hostsharing.hsadminng.domain.Membership;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import org.hostsharing.hsadminng.repository.AssetRepository;
import org.hostsharing.hsadminng.repository.CustomerRepository;
import org.hostsharing.hsadminng.repository.MembershipRepository;
import org.hostsharing.hsadminng.service.AssetService;
import org.hostsharing.hsadminng.service.AssetValidator;
import org.hostsharing.hsadminng.service.MembershipValidator;
import org.hostsharing.hsadminng.service.accessfilter.JSonBuilder;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.mapper.AssetMapper;
import org.hostsharing.hsadminng.service.mapper.AssetMapperImpl;
import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl;
import org.hostsharing.hsadminng.service.mapper.MembershipMapperImpl;
import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenAuthenticatedUser;
import static org.hostsharing.hsadminng.service.accessfilter.MockSecurityContext.givenUserHavingRole;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
@JsonTest
@SpringBootTest(classes = {
AssetMapperImpl.class,
AssetDTO.AssetJsonSerializer.class,
AssetDTO.AssetJsonDeserializer.class,
MembershipMapperImpl.class,
CustomerMapperImpl.class
})
@RunWith(SpringRunner.class)
public class AssetDTOUnitTest {
private static final Long SOME_CUSTOMER_ID = RandomUtils.nextLong(100, 199);
private static final Integer SOME_CUSTOMER_REFERENCE = 10001;
private static final String SOME_CUSTOMER_PREFIX = "abc";
private static final String SOME_CUSTOMER_NAME = "Some Customer Name";
private static final Customer SOME_CUSTOMER = new Customer().id(SOME_CUSTOMER_ID).reference(SOME_CUSTOMER_REFERENCE).prefix(SOME_CUSTOMER_PREFIX).name(SOME_CUSTOMER_NAME);
private static final Long SOME_MEMBERSHIP_ID = RandomUtils.nextLong(200, 299);
private static final LocalDate SOME_MEMBER_FROM_DATE = LocalDate.parse("2000-12-06") ;
private static final Membership SOME_MEMBERSHIP = new Membership().id(SOME_MEMBERSHIP_ID).customer(SOME_CUSTOMER).memberFromDate(SOME_MEMBER_FROM_DATE);
public static final String SOME_MEMBERSHIP_DISPLAY_LABEL = "Some Customer Name [10001:abc] 2000-12-06 - ...";
private static final Long SOME_ASSET_ID = RandomUtils.nextLong(300, 399);
private static final Asset SOME_ASSET = new Asset().id(SOME_ASSET_ID).membership(SOME_MEMBERSHIP);
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Autowired
private ObjectMapper objectMapper;
@Autowired
private AssetMapper assetMapper;
@MockBean
private AssetRepository assetRepository;
@MockBean
private AssetValidator assetValidator;
@MockBean
private CustomerRepository customerRepository;
@MockBean
private MembershipRepository membershipRepository;
@MockBean
private MembershipValidator membershipValidator;
@MockBean
private AssetService assetService;
@MockBean
private EntityManager em;
@Before
public void init() {
given(customerRepository.findById(SOME_CUSTOMER_ID)).willReturn(Optional.of(SOME_CUSTOMER));
given(membershipRepository.findById(SOME_MEMBERSHIP_ID)).willReturn(Optional.of(SOME_MEMBERSHIP));
given(assetRepository.findById(SOME_ASSET_ID)).willReturn((Optional.of(SOME_ASSET)));
}
@Test
public void shouldSerializePartiallyForFinancialCustomerContact() throws JsonProcessingException {
// given
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.FINANCIAL_CONTACT);
final AssetDTO given = createSomeAssetDTO(SOME_ASSET_ID);
// when
final String actual = objectMapper.writeValueAsString(given);
// then
given.setRemark(null);
assertEquals(createExpectedJSon(given), actual);
}
@Test
public void shouldSerializeCompletelyForSupporter() throws JsonProcessingException {
// given
givenAuthenticatedUser();
givenUserHavingRole(Role.SUPPORTER);
final AssetDTO given = createSomeAssetDTO(SOME_ASSET_ID);
// when
final String actual = objectMapper.writeValueAsString(given);
// then
assertEquals(createExpectedJSon(given), actual);
}
@Test
public void shouldNotDeserializeForContractualCustomerContact() {
// given
givenAuthenticatedUser();
givenUserHavingRole(CustomerDTO.class, SOME_CUSTOMER_ID, Role.CONTRACTUAL_CONTACT);
final String json = new JSonBuilder()
.withFieldValue("id", SOME_ASSET_ID)
.withFieldValue("remark", "Updated Remark")
.toString();
// when
final Throwable actual = catchThrowable(() -> objectMapper.readValue(json, AssetDTO.class));
// then
assertThat(actual).isInstanceOfSatisfying(BadRequestAlertException.class, bre ->
assertThat(bre.getMessage()).isEqualTo("Update of field AssetDTO.remark prohibited for current user role CONTRACTUAL_CONTACT")
);
}
@Test
public void shouldDeserializeForAdminIfRemarkIsChanged() throws IOException {
// given
givenAuthenticatedUser();
givenUserHavingRole(Role.ADMIN);
final String json = new JSonBuilder()
.withFieldValue("id", SOME_ASSET_ID)
.withFieldValue("remark", "Updated Remark")
.toString();
// when
final AssetDTO actual = objectMapper.readValue(json, AssetDTO.class);
// then
final AssetDTO expected = new AssetDTO();
expected.setId(SOME_ASSET_ID);
expected.setMembershipId(SOME_MEMBERSHIP_ID);
expected.setRemark("Updated Remark");
expected.setMembershipDisplayLabel(SOME_MEMBERSHIP_DISPLAY_LABEL);
assertThat(actual).isEqualToIgnoringGivenFields(expected, "displayLabel");
}
// --- only test fixture below ---
private String createExpectedJSon(AssetDTO dto) {
return new JSonBuilder()
.withFieldValueIfPresent("id", dto.getId())
.withFieldValueIfPresent("documentDate", dto.getDocumentDate().toString())
.withFieldValueIfPresent("valueDate", dto.getValueDate().toString())
.withFieldValueIfPresent("action", dto.getAction().name())
.withFieldValueIfPresent("amount", dto.getAmount().doubleValue())
.withFieldValueIfPresent("remark", dto.getRemark())
.withFieldValueIfPresent("membershipId", dto.getMembershipId())
.withFieldValue("membershipDisplayLabel", dto.getMembershipDisplayLabel())
.toString();
}
private AssetDTO createSomeAssetDTO(final long id) {
final AssetDTO given = new AssetDTO();
given.setId(id);
given.setAction(AssetAction.PAYMENT);
given.setAmount(new BigDecimal("512.01"));
given.setDocumentDate(LocalDate.parse("2019-04-27"));
given.setValueDate(LocalDate.parse("2019-04-28"));
given.setMembershipId(SOME_MEMBERSHIP_ID);
given.setRemark("Some Remark");
given.setMembershipDisplayLabel("Display Label for Membership #" + SOME_MEMBERSHIP_ID);
return given;
}
}

View File

@ -7,6 +7,7 @@ import org.hostsharing.hsadminng.domain.enumeration.CustomerKind;
import org.hostsharing.hsadminng.domain.enumeration.VatRegion; import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
import org.hostsharing.hsadminng.repository.CustomerRepository; import org.hostsharing.hsadminng.repository.CustomerRepository;
import org.hostsharing.hsadminng.service.CustomerService; import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.accessfilter.JSonBuilder;
import org.hostsharing.hsadminng.service.accessfilter.Role; import org.hostsharing.hsadminng.service.accessfilter.Role;
import org.hostsharing.hsadminng.service.mapper.CustomerMapper; import org.hostsharing.hsadminng.service.mapper.CustomerMapper;
import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl; import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl;
@ -78,13 +79,12 @@ public class CustomerDTOUnitTest {
String actual = objectMapper.writeValueAsString(given); String actual = objectMapper.writeValueAsString(given);
// then // then
final String expectedJSon = "{" + final String expectedJSon = new JSonBuilder()
toJSonFieldDefinition("id", given.getId()) + "," + .withFieldValue("id", given.getId())
toJSonFieldDefinition("reference", given.getReference()) + "," + .withFieldValue("reference", given.getReference())
toJSonFieldDefinition("prefix", given.getPrefix()) + "," + .withFieldValue("prefix", given.getPrefix())
toJSonFieldDefinition("name", given.getName()) + "," + .withFieldValue("name", given.getName())
toJSonFieldDefinition("displayLabel", given.getDisplayLabel()) + .withFieldValue("displayLabel", given.getDisplayLabel()).toString();
"}";
assertEquals(expectedJSon, actual); assertEquals(expectedJSon, actual);
} }
@ -125,49 +125,24 @@ public class CustomerDTOUnitTest {
// --- only test fixture below --- // --- only test fixture below ---
private String createExpectedJSon(CustomerDTO dto) { private String createExpectedJSon(CustomerDTO dto) {
String json = // the fields in alphanumeric order: return new JSonBuilder()
toJSonFieldDefinitionIfPresent("id", dto.getId()) + .withFieldValueIfPresent("id", dto.getId())
toJSonFieldDefinitionIfPresent("reference", dto.getReference()) + .withFieldValueIfPresent("reference", dto.getReference())
toJSonFieldDefinitionIfPresent("prefix", dto.getPrefix()) + .withFieldValueIfPresent("prefix", dto.getPrefix())
toJSonFieldDefinitionIfPresent("name", dto.getName()) + .withFieldValueIfPresent("name", dto.getName())
toJSonFieldDefinitionIfPresent("kind", "LEGAL") + .withFieldValueIfPresent("kind", "LEGAL")
toJSonNullFieldDefinition("birthDate") + .toJSonNullFieldDefinition("birthDate")
toJSonNullFieldDefinition("birthPlace") + .toJSonNullFieldDefinition("birthPlace")
toJSonFieldDefinitionIfPresent("registrationCourt", "Registergericht") + .withFieldValueIfPresent("registrationCourt", "Registergericht")
toJSonFieldDefinitionIfPresent("registrationNumber", "Registernummer") + .withFieldValueIfPresent("registrationNumber", "Registernummer")
toJSonFieldDefinitionIfPresent("vatRegion", "DOMESTIC") + .withFieldValueIfPresent("vatRegion", "DOMESTIC")
toJSonFieldDefinitionIfPresent("vatNumber", "DE1234") + .withFieldValueIfPresent("vatNumber", "DE1234")
toJSonFieldDefinitionIfPresent("contractualSalutation", dto.getContractualSalutation()) + .withFieldValueIfPresent("contractualSalutation", dto.getContractualSalutation())
toJSonFieldDefinitionIfPresent("contractualAddress", dto.getContractualAddress()) + .withFieldValueIfPresent("contractualAddress", dto.getContractualAddress())
toJSonFieldDefinitionIfPresent("billingSalutation", dto.getBillingSalutation()) + .withFieldValueIfPresent("billingSalutation", dto.getBillingSalutation())
toJSonFieldDefinitionIfPresent("billingAddress", dto.getBillingAddress()) + .withFieldValueIfPresent("billingAddress", dto.getBillingAddress())
toJSonFieldDefinitionIfPresent("remark", dto.getRemark()) + .withFieldValueIfPresent("remark", dto.getRemark())
toJSonFieldDefinitionIfPresent("displayLabel", dto.getDisplayLabel()); .withFieldValueIfPresent("displayLabel", dto.getDisplayLabel()).toString();
return "{" + json.substring(0, json.length() - 1) + "}";
}
private String toJSonFieldDefinition(String name, String value) {
return inQuotes(name) + ":" + (value != null ? inQuotes(value) : "null");
}
private String toJSonFieldDefinition(String name, Number value) {
return inQuotes(name) + ":" + (value != null ? value : "null");
}
private String toJSonNullFieldDefinition(String name) {
return inQuotes(name) + ":null,";
}
private String toJSonFieldDefinitionIfPresent(String name, String value) {
return value != null ? inQuotes(name) + ":" + inQuotes(value) + "," : "";
}
private String toJSonFieldDefinitionIfPresent(String name, Number value) {
return value != null ? inQuotes(name) + ":" + value + "," : "";
}
private String inQuotes(Object value) {
return "\"" + value.toString() + "\"";
} }
private CustomerDTO createSomeCustomerDTO(final long id) { private CustomerDTO createSomeCustomerDTO(final long id) {