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

@ -22,7 +22,7 @@ public class Asset implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_NAME = "asset";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@ -59,6 +59,11 @@ public class Asset implements Serializable {
return id;
}
public Asset id(Long id) {
this.id = id;
return this;
}
public void setId(Long 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.service.AssetService;
import org.hostsharing.hsadminng.service.CustomerService;
import org.hostsharing.hsadminng.service.MembershipService;
import org.hostsharing.hsadminng.service.accessfilter.*;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.ApplicationContext;
@ -40,13 +40,15 @@ public class AssetDTO implements Serializable, AccessMappings {
private BigDecimal amount;
@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;
@ParentId(resolver = CustomerService.class)
@ParentId(resolver = MembershipService.class)
@AccessFor(init = Role.ADMIN, update = Role.ADMIN, read = {Role.CONTRACTUAL_CONTACT, Role.FINANCIAL_CONTACT})
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})
private String membershipDisplayLabel;

View File

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

View File

@ -1,11 +1,14 @@
package org.hostsharing.hsadminng.service.accessfilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.List;
public class JSonBuilder {
private StringBuilder json = new StringBuilder();
@SafeVarargs
public static String asJSon(final ImmutablePair<String, Object>... properties) {
final StringBuilder json = new StringBuilder();
@ -14,15 +17,8 @@ public class JSonBuilder {
json.append(": ");
if (prop.right instanceof Number) {
json.append(prop.right);
} else if (prop.right instanceof List) {
json.append("[");
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 if (prop.right instanceof List) {
json.append(toJSonArray(prop.right));
} else {
json.append(inQuotes(prop.right));
}
@ -31,6 +27,50 @@ public class JSonBuilder {
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) {
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.repository.CustomerRepository;
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.mapper.CustomerMapper;
import org.hostsharing.hsadminng.service.mapper.CustomerMapperImpl;
@ -78,13 +79,12 @@ public class CustomerDTOUnitTest {
String actual = objectMapper.writeValueAsString(given);
// then
final String expectedJSon = "{" +
toJSonFieldDefinition("id", given.getId()) + "," +
toJSonFieldDefinition("reference", given.getReference()) + "," +
toJSonFieldDefinition("prefix", given.getPrefix()) + "," +
toJSonFieldDefinition("name", given.getName()) + "," +
toJSonFieldDefinition("displayLabel", given.getDisplayLabel()) +
"}";
final String expectedJSon = new JSonBuilder()
.withFieldValue("id", given.getId())
.withFieldValue("reference", given.getReference())
.withFieldValue("prefix", given.getPrefix())
.withFieldValue("name", given.getName())
.withFieldValue("displayLabel", given.getDisplayLabel()).toString();
assertEquals(expectedJSon, actual);
}
@ -125,49 +125,24 @@ public class CustomerDTOUnitTest {
// --- only test fixture below ---
private String createExpectedJSon(CustomerDTO dto) {
String json = // the fields in alphanumeric order:
toJSonFieldDefinitionIfPresent("id", dto.getId()) +
toJSonFieldDefinitionIfPresent("reference", dto.getReference()) +
toJSonFieldDefinitionIfPresent("prefix", dto.getPrefix()) +
toJSonFieldDefinitionIfPresent("name", dto.getName()) +
toJSonFieldDefinitionIfPresent("kind", "LEGAL") +
toJSonNullFieldDefinition("birthDate") +
toJSonNullFieldDefinition("birthPlace") +
toJSonFieldDefinitionIfPresent("registrationCourt", "Registergericht") +
toJSonFieldDefinitionIfPresent("registrationNumber", "Registernummer") +
toJSonFieldDefinitionIfPresent("vatRegion", "DOMESTIC") +
toJSonFieldDefinitionIfPresent("vatNumber", "DE1234") +
toJSonFieldDefinitionIfPresent("contractualSalutation", dto.getContractualSalutation()) +
toJSonFieldDefinitionIfPresent("contractualAddress", dto.getContractualAddress()) +
toJSonFieldDefinitionIfPresent("billingSalutation", dto.getBillingSalutation()) +
toJSonFieldDefinitionIfPresent("billingAddress", dto.getBillingAddress()) +
toJSonFieldDefinitionIfPresent("remark", dto.getRemark()) +
toJSonFieldDefinitionIfPresent("displayLabel", dto.getDisplayLabel());
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() + "\"";
return new JSonBuilder()
.withFieldValueIfPresent("id", dto.getId())
.withFieldValueIfPresent("reference", dto.getReference())
.withFieldValueIfPresent("prefix", dto.getPrefix())
.withFieldValueIfPresent("name", dto.getName())
.withFieldValueIfPresent("kind", "LEGAL")
.toJSonNullFieldDefinition("birthDate")
.toJSonNullFieldDefinition("birthPlace")
.withFieldValueIfPresent("registrationCourt", "Registergericht")
.withFieldValueIfPresent("registrationNumber", "Registernummer")
.withFieldValueIfPresent("vatRegion", "DOMESTIC")
.withFieldValueIfPresent("vatNumber", "DE1234")
.withFieldValueIfPresent("contractualSalutation", dto.getContractualSalutation())
.withFieldValueIfPresent("contractualAddress", dto.getContractualAddress())
.withFieldValueIfPresent("billingSalutation", dto.getBillingSalutation())
.withFieldValueIfPresent("billingAddress", dto.getBillingAddress())
.withFieldValueIfPresent("remark", dto.getRemark())
.withFieldValueIfPresent("displayLabel", dto.getDisplayLabel()).toString();
}
private CustomerDTO createSomeCustomerDTO(final long id) {