I am writing test unit for my backend project. Also I am using ModelMapper for map functions. But when I write getAll() or update() etc. at test method from manager ProductManager, Spring says
org.modelmapper.ModelMapper.map(Object, java.lang.Class)" because the return value of "hakan.productData.core.utilities.mappers.ModelMapperService.forRequest()" is null
I didn't figure it out. Can you help me please?
ProductManager =
@Service
@AllArgsConstructor
@Transactional
public class ProductManager implements ProductService {
private ProductRepository productRepository;
private ProductBusinessRules productBusinessRules;
private ModelMapperService modelMapperService;
@Override
@Transactional(readOnly = true)
public List<GetAllProductsResponse> getAll() {
List<Product> products = productRepository.findAll();
List<GetAllProductsResponse> productsResponse= products.stream()
.map(product -> this.modelMapperService.forResponse().map(product, GetAllProductsResponse.class)).collect(Collectors.toList());
return productsResponse;
}
@Override
public void add(CreateProductRequest createProductRequest) {
this.productBusinessRules.checkIfProductNameExists(createProductRequest.getName());
Product product = this.modelMapperService.forRequest().map(createProductRequest,Product.class);
this.productRepository.save(product);
}
@Override
public UpdateProductRequest update(UpdateProductRequest updateProductRequest) {
Product product = this.modelMapperService.forRequest().map(updateProductRequest,Product.class);
this.productRepository.save(product);
return updateProductRequest;
}
ModelMapperManager =
@Service
@AllArgsConstructor
public class ModelMapperManager implements ModelMapperService {
private ModelMapper modelMapper;
@Override
public ModelMapper forResponse() {
this.modelMapper.getConfiguration()
.setAmbiguityIgnored(true)
.setMatchingStrategy(MatchingStrategies.LOOSE);
return this.modelMapper;
}
@Override
public ModelMapper forRequest() {
this.modelMapper.getConfiguration()
.setAmbiguityIgnored(true)
.setMatchingStrategy(MatchingStrategies.STANDARD);
return this.modelMapper;
}
}
ProductManagerTest =
@ExtendWith(MockitoExtension.class)
public class ProductManagerTest {
@Mock
private ProductRepository productRepository;
@Mock
private ProductBusinessRules productBusinessRules;
@Mock
private ModelMapperService modelMapperService;
@Mock
private ModelMapperManager modelMapper;
@InjectMocks
private ProductManager productManager;
@Test
@DisplayName("Should Find Post By Id")
void shouldFindPostById() {
Product product = new Product(123,"Milk","Drink",10,true,5);
GetAllProductsResponse expectedProductResponse = new GetAllProductsResponse(123,"Milk","Drink",10,true,5);
Mockito.when(productRepository.findById(123)).thenReturn(Optional.of(product));
Optional<Product> actualPostResponse = productManager.getById(123);
assertThat(actualPostResponse.get().getId()).isEqualTo(expectedProductResponse.getId());
assertThat(actualPostResponse.get().getName()).isEqualTo(expectedProductResponse.getName());
System.out.println("Test was successful");
}
@Test
@DisplayName("Should Update By If")
void shouldUpdateById(){
Product product = Product.builder()
.name("Milk")
.category("Drink")
.price(10)
.quantity(10)
.onOffer(true)
.build();
UpdateProductRequest getAllProductsResponse = UpdateProductRequest.builder()
.id(1)
.name("Coke")
.category("Drink")
.price(5)
.quantity(10)
.onOffer(true)
.build();
when(productRepository.save(Mockito.any(Product.class))).thenReturn(product);
when(productRepository.findById(0)).thenReturn(Optional.ofNullable(product));
UpdateProductRequest updatedProduct = productManager.update(getAllProductsResponse);
assertThat(updatedProduct).isNotNull();
}
}
shouldFindPostById test method works fine because I did not use any mapper methods but the other doesn't work.
I think your problem is that you try to mock interface ModelMapperService
in your test class, but you do not mock class ModelMapperManager
. It means that when you call method modelMapperService.forRequest()
, it returns null
value.
Updated code:
@ExtendWith(MockitoExtension.class)
public class ProductManagerTest {
@Mock
private ProductRepository productRepository;
@Mock
private ProductBusinessRules productBusinessRules;
@Mock
private ModelMapperManager modelMapperManager;
@Mock
private ModelMapper modelMapper;
@InjectMocks
private ProductManager productManager;
@Test
@DisplayName("Should Update By If")
void shouldUpdateById() {
Product product = Product.builder()
.name("Milk")
.category("Drink")
.price(10)
.quantity(10)
.onOffer(true)
.build();
UpdateProductRequest updateProductRequest = UpdateProductRequest.builder()
.id(1)
.name("Coke")
.category("Drink")
.price(5)
.quantity(10)
.onOffer(true).build();
when(modelMapperManager.forRequest()).thenReturn(modelMapper);
when(productRepository.save(Mockito.any(Product.class))).thenReturn(product);
when(productRepository.findById(0)).thenReturn(Optional.ofNullable(product));
UpdateProductRequest updatedProduct = productManager.update(updateProductRequest);
assertThat(updatedProduct).isNotNull();
}
}