Basically I just would like to test my mapper which should be auto generated by MapStruct.
I tried all annotations possible and this answer seems to be the best solution in order to work with sprinboot and junit 5 although it still does not work in my eclipse, somehow it just shows an error as seen below saying ProductMapperImpl cannot be resolved to a type
although it should be autogenerated trough @Mapper annotation.
For example I am also using Lombok Annotation and all these auto generated methods eclipse recognizes and works absolutely fine.
So what did I do wrong? Maybe there is another way to autowire mapper interface to test class so that it works? Maybe it is something with the generated-sources folders and just eclipse somehow not recognizing it?
TestClass
@Slf4j
@SpringBootTest(classes = { ProductMapperImpl.class })
class ProductMapperTest {
@Autowired
private ProductMapper productMapper;
@BeforeAll
public static void setup() {
log.info("Testing mapper between product entity and product dto...");
}
@Test
public void test() {
String hello = "Hello";
assertTrue("Hello".equals(hello));
}
@Test
public void shouldMapProductToDto() {
// given
User user1 = new User("username_1", "1", Role.STORE);
RetailStore store1 = new RetailStore(user1, "store", "1234", "store@example.org");
Category cat1 = new Category("vegetables");
Product entity = new Product(cat1, "cucumber", new BigDecimal(0.99), store1);
// when
System.out.println(entity);
ProductDto dto = productMapper.productToProductDto(entity);
// then
assertNotNull(dto);
assertEquals(dto.getCategoryName(), entity.getCategory().getCatName());
assertEquals(dto.getName(), entity.getName());
assertEquals(dto.getPrice(), entity.getPrice());
assertEquals(dto.getProductId(), entity.getProductId());
assertEquals(dto.getStoreId(), entity.getRetailStore().getStoreId());
}
@Test
public void shouldMapDtoToProduct() {
// given
ProductDto dto = new ProductDto();
dto.setCategoryName("vegetables");
dto.setDescription("description");
dto.setLimitations("limitations");
dto.setName("cucumber");
dto.setPrice(new BigDecimal(1.99));
dto.setProductId(1L);
dto.setRemainingStock(1);
dto.setStoreId(1L);
// when
Product entity = productMapper.productDtoToProduct(dto);
// then
assertNotNull(entity);
assertEquals(entity.getCategory().getCatName(), dto.getCategoryName());
assertEquals(entity.getDescription(), dto.getDescription());
assertEquals(entity.getLimitations(), dto.getLimitations());
assertEquals(entity.getName(), dto.getName());
assertEquals(entity.getPrice(), dto.getPrice());
assertEquals(entity.getProductId(), dto.getProductId());
assertEquals(entity.getRemainingStock(), dto.getRemainingStock());
assertEquals(entity.getRetailStore().getStoreId(), dto.getStoreId());
assertEquals(entity.getRetailStore().getStoreId(), dto.getStoreId());
}
}
MapperClass
@Mapper(componentModel = "spring")
public interface ProductMapper {
/**
* Map product entity instance to product Dto instance.
*
* @param product entity product
* @return dto product
*/
@Mappings({ @Mapping(source = "category.catName", target = "categoryName"),
@Mapping(source = "retailStore.storeId", target = "storeId") })
ProductDto productToProductDto(Product product);
/**
* Map product Dto instance to product entity instance.
*
* @param productDto dto product
* @return entity product
*/
@Mappings({ @Mapping(source = "categoryName", target = "category.catName"),
@Mapping(source = "storeId", target = "retailStore.storeId") })
Product productDtoToProduct(ProductDto productDto);
/**
* Update product with the latest values from a product DTO.
*
* @param productDto dto product
* @param product entity product
*/
@Mappings({ @Mapping(source = "categoryName", target = "category.catName"),
@Mapping(source = "storeId", target = "retailStore.storeId") })
void updateModel(ProductDto productDto, @MappingTarget Product product);
// aggregated root
/**
* Map list of product entities to list of product DTOs.
*
* @param products List of product entities
* @return list of product dto`s
*/
@Mappings({ @Mapping(source = "category.catName", target = "categoryName"),
@Mapping(source = "retailStore.storeId", target = "storeId") })
List<ProductDto> toProductDtos(List<Product> products);
}
product dto
@Data
public class ProductDto {
private Long productId;
private String name;
private String categoryName;
private Long storeId;
private BigDecimal price;
private byte[] picture;
private String description;
private String limitations;
private Integer remainingStock;
}
product entity
@Data
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "product_id")
private Long productId;
// defines foreign key column category_id and indicates the owner of the
// ManyToOne relationship
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
@Lob
@Basic
private byte[] picture;
private String name;
private BigDecimal price;
// defines foreign key column store_id and indicates the owner of the ManyToOne
// relationship
@JsonBackReference(value = "product-store")
@ManyToOne
@JoinColumn(name = "store_id")
private RetailStore retailStore;
private String description;
private String limitations;
@Column(name = "remaining_stock")
private Integer remainingStock;
/**
* Constructor.
*/
protected Product() {
}
/**
* Constructor.
*
* @param category category of the product
* @param name name of the product
* @param price price of the product
* @param retailStore retail store selling this product
*/
public Product(Category category, String name, BigDecimal price, RetailStore retailStore) {
super();
this.category = category;
this.name = name;
this.price = price;
this.retailStore = retailStore;
}
/**
* Converting bigDecimal scale (number of digits to the right of the decimal
* point) of price to 2.
*/
@PrePersist
@PreUpdate
public void pricePrecisionConvertion() {
this.price.setScale(2, RoundingMode.HALF_UP);
}