我正在为我的服务层编写单元测试。我的服务层有多个自动装配的字段。我想模拟其中一个和其他人初始化为自动装配。
服务接口
public interface ProductSupplierService {
Map<String, List<? extends BaseDTO>> getProductSuppliers(Long productId, Long tenantId);
ProductSupplierDTO addProductSupplier(Long productId, Long tenantId, ProductSupplierDTO productSupplierDTO);
ProductSupplierDTO editProductSupplier(Long productId, Long supplierId, Long tenantId,
ProductSupplierDTO productSupplierDTO);
void deleteProductSupplier(Long productId, Long supplierId, Long tenantId);
}
服务实施
@Service
public class ProductSupplierServiceImpl implements ProductSupplierService {
private MapperFacade mapper;
@Autowired
public void setMapperFactory(MapperFactory mapperFactory) {
this.mapper = mapperFactory.getMapperFacade();
}
@Autowired
private ProductRepository productRepository;
@Autowired
private ProductManager productManager;
private static final Logger log = LoggerFactory.getLogger(ProductSupplierServiceImpl.class);
@Override
public Map < String, List << ? extends BaseDTO >> getProductSuppliers(Long productId, Long tenantId) {
Product product = fetchProductByProductIdAndTenantId(productId, tenantId);
ListResponse listResponse = new ListResponse();
if (CollectionUtil.nonNullNonEmpty(product.getProductSuppliers())) {
List < ProductSupplierDTO > productSupplierDTOS = new ArrayList < > (0);
product.getProductSuppliers().stream().filter(Objects::nonNull)
.forEach(productSupplier - > productSupplierDTOS
.add(productSupplier.toDTO(ProductSupplierDTO.class, mapper)));
listResponse.addResponse("product_suppliers", productSupplierDTOS);
}
return listResponse.getResponse();
}
@Override
public ProductSupplierDTO addProductSupplier(Long productId, Long tenantId, ProductSupplierDTO productSupplierDTO) {
Product product = fetchProductByProductIdAndTenantId(productId, tenantId);
ProductSupplier productSupplier = productSupplierDTO.toModel(ProductSupplier.class, mapper);
if (product.getProductSuppliers().add(productSupplier)) {
productManager.applyProductSupplier(product, tenantId, productSupplier);
product.setModified(new Date());
try {
productRepository.save(product);
Optional < ProductSupplier > savedProductSupplier = product.getProductSuppliers().stream()
.filter(Objects::nonNull)
.filter(ps - > ps.getSupplierId().equals(productSupplierDTO.getSupplierId())).findFirst();
if (savedProductSupplier.isPresent()) {
return savedProductSupplier.get().toDTO(ProductSupplierDTO.class, mapper);
} else {
throw new UnexpectedException();
}
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UnexpectedException();
}
} else {
throw new BusinessValidationException("supplier already exists");
}
}
@Override
public ProductSupplierDTO editProductSupplier(Long productId, Long supplierId, Long tenantId,
ProductSupplierDTO productSupplierDTO) {
Product product = fetchProductByProductIdAndTenantId(productId, tenantId);
Optional < ProductSupplier > productSupplierOptional = product.getProductSuppliers().stream()
.filter(Objects::nonNull)
.filter(productSupplier - > productSupplier.getSupplierId().equals(supplierId)).findFirst();
if (productSupplierOptional.isPresent()) {
ProductSupplier productSupplier = productSupplierOptional.get();
if (Objects.nonNull(productSupplierDTO.getBuyPrice())) {
productSupplier.setBuyPrice(productSupplierDTO.getBuyPrice());
}
if (Objects.nonNull(productSupplierDTO.isDefaultSupplier())) {
if (productSupplierDTO.isDefaultSupplier()) {
product.getProductSuppliers().forEach(supplier - > supplier.setDefaultSupplier(false));
productSupplier.setDefaultSupplier(true);
} else {
productSupplier.setDefaultSupplier(false);
}
}
productSupplier.setModified(new Date());
product.setModified(new Date());
try {
productRepository.save(product);
return productSupplier.toDTO(ProductSupplierDTO.class, mapper);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UnexpectedException();
}
} else {
throw new EntityNotFoundException(ProductSupplier.class, String.valueOf(supplierId));
}
}
@Override
public void deleteProductSupplier(Long productId, Long supplierId, Long tenantId) {
Product product = fetchProductByProductIdAndTenantId(productId, tenantId);
Optional < ProductSupplier > productSupplierOptional = product.getProductSuppliers().stream()
.filter(Objects::nonNull)
.filter(productSupplier - > productSupplier.getSupplierId().equals(supplierId)).findFirst();
if (productSupplierOptional.isPresent()) {
product.getProductSuppliers().remove(productSupplierOptional.get());
product.setModified(new Date());
try {
productRepository.save(product);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new UnexpectedException();
}
} else {
throw new EntityNotFoundException(ProductSupplier.class, String.valueOf(supplierId));
}
}
private Product fetchProductByProductIdAndTenantId(Long productId, Long tenantId) {
Product product = productRepository.findByIdAndTenantId(productId, tenantId);
if (Objects.nonNull(product)) {
return product;
} else {
throw new EntityNotFoundException(Product.class, String.valueOf(productId));
}
}
}
测试课
@RunWith(MockitoJUnitRunner.class)
public class ProductSupplierServiceUnitTest {
@Mock
private ProductRepository productRepository;
@Autowired
@InjectMocks
private ProductSupplierServiceImpl productSupplierService;
@Test(expected = EntityNotFoundException.class)
public void productNotFound() {
Mockito.when(productRepository.findByIdAndTenantId(invalidProductId, tenantId)).thenReturn(null);
productSupplierService.getProductSuppliers(invalidProductId, tenantId);
}
@Test
public void getProductSuppliersSuccess() {
initProduct();
initProductSupplier();
Set < ProductSupplier > productSuppliers = new HashSet < > (Collections.singletonList(productSupplierBuilder.get()));
Product product = productBuilder.setProductSuppliers(productSuppliers).get();
product.setId(validProductId);
Mockito.when(productRepository.findByIdAndTenantId(validProductId, tenantId)).thenReturn(product);
Map < String, List << ? extends BaseDTO >> result = productSupplierService.getProductSuppliers(validProductId,
tenantId);
Assert.assertEquals(result.size(), 1);
Assert.assertTrue(result.containsKey("product_suppliers"));
}
@Test
public void getProductSuppliersEmpty() {
initProduct();
initProductSupplier();
Product product = productBuilder.setProductSuppliers(Collections.emptySet()).get();
product.setId(validProductId);
Mockito.when(productRepository.findByIdAndTenantId(validProductId, tenantId)).thenReturn(product);
Map < String, List << ? extends BaseDTO >> result = productSupplierService.getProductSuppliers(validProductId,
tenantId);
Assert.assertTrue(result.isEmpty());
}
}
我只想模拟productRepository字段,而是productManager&amp;映射器字段必须自动初始化。
问题是productManager&amp;运行测试时映射器字段为空。
是否可以自动初始化它们?就像在使用完全加载的上下文运行spring boot应用程序时初始化它们一样。
答案 0 :(得分:0)
如果是“productManager”&amp; “mapper”是简单的类,只需添加:
@Spy
ProductManager productManager = new ProductManager();
@Spy
Mapper mapper = new Mapper();
Mockito知道使用@Spy为@InjectMocks注释的对象。如果这些类具有自己的@Autowired字段,那么它超出了Mockito的功能,常见的解决方案是使用SpringJUnit4ClassRunner并在Spring上下文配置中使用Mockito:
<bean id="mockBean" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="some.real.bean.Class" />
</bean>
答案 1 :(得分:0)
要回答@Harshit的最新评论中的问题,可以为测试配置上下文:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ExampleTestConfiguration.class})
...在ExampleTestConfiguration的@ComponentScan中定义包含和排除的包