Witam
aktualnie wlaczę z testami i będę wdzięczny za informacje co robi nie tak.
Mam prosty model danych:
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "contractors")
@Inheritance(strategy = InheritanceType.JOINED)
public class Contractor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fullName;
private String shortName;
@OneToOne
@JoinColumn(name = "address_id")
private Address address;
private String vatNumber;
private String description;
private Integer termOfPayment;
private BigDecimal balance;
@OneToMany(mappedBy = "contractor", fetch = FetchType.EAGER)
private List<ContactPerson> contactPersons = new ArrayList<>();
}
Encje główną rozszerza Customer, i o nim jest teraz mowa w tym poście:
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "customers")
public class Customer extends Contractor {
@OneToMany(mappedBy = "customer", fetch = FetchType.EAGER)
private List<Cargo> cargos = new ArrayList<>();
@Enumerated(EnumType.STRING)
private PaymentRating paymentRating;
@OneToMany(mappedBy = "customer", fetch = FetchType.EAGER)
private List<WarehouseOrder> warehouseOrders = new ArrayList<>();
@OneToMany(mappedBy = "customer", fetch = FetchType.EAGER)
private List<CustomerInvoice> customerInvoices = new ArrayList<>();
}
DTO:
@Getter
@Setter
public class CustomerDTO {
private Long id;
@NotBlank(message = "Full name cannot be null")
private String fullName;
private String shortName;
private Long addressId;
@Pattern(regexp = "^[A-Z]{2}\\d{8,}$", message = "Invalid VAT number")
private String vatNumber;
private String description;
@NotNull(message = "Term of payment cannot be null")
@Min(1)
private Integer termOfPayment;
@NotEmpty(message = "Contact person IDs cannot be null")
private List<@Positive(message = "Goods ID must be a positive number") Long> contactPersonIds;
}
MAPPER:
public Customer mapToEntity(CustomerDTO customerDTO){
if (customerDTO == null){
throw new NullEntityException("Customer data cannot be null");
}
Customer customer = new Customer();
customer.setId(customerDTO.getId());
customer.setFullName(customerDTO.getFullName());
customer.setShortName(customerDTO.getShortName());
Address address = addressRepository.findById(customerDTO.getAddressId()).orElseThrow(() -> new AddressNotFoundException("Address not found"));
customer.setAddress(address);
customer.setVatNumber(customerDTO.getVatNumber());
customer.setDescription(customerDTO.getDescription());
customer.setTermOfPayment(customerDTO.getTermOfPayment());
List<ContactPerson> contact = customerDTO.getContactPersonIds().stream()
.map(contactPersonIds -> contactPersonRepository.findById(contactPersonIds)
.orElseThrow(() -> new ContactPersonNotFoundException("Contact Person not found with this ID " + contactPersonIds)))
.collect(Collectors.toList());
customer.setContactPersons(contact);
return customer;
}
public CustomerDTO mapToDTO(Customer customer){
if (customer == null){
throw new NullEntityException("Customer cannot be null");
}
CustomerDTO dto = new CustomerDTO();
dto.setId(customer.getId());
dto.setFullName(customer.getFullName());
dto.setShortName(customer.getShortName());
List<Long> contactPersons = customer.getContactPersons().stream().map(ContactPerson::getId).collect(Collectors.toList());
dto.setContactPersonIds(contactPersons);
dto.setVatNumber(customer.getVatNumber());
dto.setAddressId(customer.getAddress().getId());
dto.setDescription(customer.getDescription());
dto.setTermOfPayment(customer.getTermOfPayment());
return dto;
}
SERWIS:
public List<CustomerDTO> findAllCustomersSortedBy(String sortBy) {
return customerRepository.findAllCustomersBy(sortBy).stream().map(customerMapper::mapToDTO).collect(Collectors.toList());
}
@Transactional
public CustomerDTO addCustomer(CustomerDTO customerDTO) {
Customer customer = customerMapper.mapToEntity(customerDTO);
addAdditionalDataForCustomer(customer);
addAdditionalDataForContactPerson(customer);
Customer saved = customerRepository.save(customer);
return customerMapper.mapToDTO(saved);
}
private static void addAdditionalDataForContactPerson(Customer customer) {
List<ContactPerson> contactPersons = customer.getContactPersons();
if (!contactPersons.isEmpty()) {
contactPersons.forEach(person -> person.setContractor(customer));
}
}
private static void addAdditionalDataForCustomer(Customer customer) {
customer.setBalance(BigDecimal.ZERO);
customer.setPaymentRating(PaymentRating.NONE);
}
REPO:
@Query("SELECT c FROM Customer c ORDER BY " +
"CASE WHEN :sortBy = 'fullName' THEN c.fullName END ASC, " +
"CASE WHEN :sortBy = 'shortName' THEN c.shortName END ASC, " +
"CASE WHEN :sortBy = 'vatNumber' THEN c.vatNumber END ASC")
List<Customer> findAllCustomersBy(@Param("sortBy") String sortBy);
Problem mam z testami do dwóch metod jakie widać w serwisie, do tej która zwraca liste klientów i ją sortuje oraz do metody która dodaje klienta. Obie te metody działają poprawnie kiedy testuje to sobie w Postmanie, wiec chyba mam jakiś problem w testach.
TESTY:
@Test
@DisplayName("Should find all sorted Customers")
public void testFindAllCustomersSorted_Success(){
Customer customer1 = prepareFirstCustomer();
Customer customer2 = prepareSecondCustomer();
CustomerDTO customerDTO1 = prepareFirstDTO();
CustomerDTO customerDTO2 = prepareSecondDTO();
List<Customer> sortedCustomers = Arrays.asList(customer2, customer1);
when(customerRepository.findAllCustomersBy("fullName")).thenReturn(sortedCustomers);
when(customerMapper.mapToDTO(customer1)).thenReturn(customerDTO1);
when(customerMapper.mapToDTO(customer2)).thenReturn(customerDTO2);
List<CustomerDTO> sortedResult = customerService.findAllCustomersSortedBy("fullName");
assertEquals(customerDTO1, sortedResult.get(0));
verify(customerRepository, times(1)).findAllCustomersBy("fullName");
}
private CustomerDTO prepareFirstDTO() {
CustomerDTO customerDTO = new CustomerDTO();
customerDTO.setId(1L);
customerDTO.setFullName("ABC SPED");
return customerDTO;
}
private CustomerDTO prepareSecondDTO() {
CustomerDTO customerDTO = new CustomerDTO();
customerDTO.setId(2L);
customerDTO.setFullName("XYZ SPED");
return customerDTO;
}
private static Customer prepareSecondCustomer() {
Customer customer = new Customer();
customer.setId(2L);
customer.setFullName("XYZ SPED");
return customer;
}
private static Customer prepareFirstCustomer() {
Customer customer = new Customer();
customer.setId(1L);
customer.setFullName("ABC SPED");
return customer;
}
Wg. mnie na pierwszym miejscu powinien znaleźć się ABC SPED, jednak dostaje błąd
org.opentest4j.AssertionFailedError:
Expected :com.tsl.dtos.CustomerDTO@5dda6f9
Actual :com.tsl.dtos.CustomerDTO@10027fc9
Oczekuje że na pierwszym miejscu bedzie XYZ, nie rozumiem dlaczego. Tak jak wspomniałem wyżej, metoda ta działa poprawnie, zwraca mi posortowaną liste.
I drugi, większy problem, test metody która dodaje klienta:
@Test
@DisplayName("Should add new Customer")
public void testAddCustomer_Success(){
CustomerDTO customerDTO = new CustomerDTO();
customerDTO.setFullName("John Doe");
customerDTO.setAddressId(1L);
customerDTO.setTermOfPayment(30);
customerDTO.setContactPersonIds(Arrays.asList(1L, 2L));
Address address = new Address();
address.setId(1L);
ContactPerson contactPerson1 = new ContactPerson();
contactPerson1.setId(1L);
ContactPerson contactPerson2 = new ContactPerson();
contactPerson2.setId(2L);
when(addressRepository.findById(1L)).thenReturn(Optional.of(address));
when(contactPersonRepository.findById(1L)).thenReturn(Optional.of(contactPerson1));
when(contactPersonRepository.findById(2L)).thenReturn(Optional.of(contactPerson2));
CustomerDTO result = customerService.addCustomer(customerDTO);
verify(customerRepository, times(1)).save(any());
assertEquals("John Doe", result.getFullName());
assertEquals(1L, result.getAddressId());
assertEquals(30, result.getTermOfPayment());
assertEquals(Arrays.asList(1L, 2L), result.getContactPersonIds());
}
Tutaj cały czas mi krzyczy ze Customer to null
java.lang.NullPointerException: Cannot invoke "com.tsl.model.contractor.Customer.setBalance(java.math.BigDecimal)" because "customer" is null