如何解决ModelMapper使用JUnit Mockito抛出NPE
我正在使用modelmapper进行NPE
CatalogServiceTest
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBoottest
public class CatalogServiceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@InjectMocks private CatalogService service;
@Mock modelmapper modelmapper;
@Mock CatalogMapper catalogMapper;
@Mock CatalogRepository catalogRepository;
@Before
public void setUp() throws Exception {
// MockitoAnnotations.initMocks(this);
CatalogEntity catalogEntity = new CatalogEntity();
catalogEntity.setId("id");
catalogEntity.setCode("code");
catalogEntity.setType("type");
catalogEntity.setValue("value");
// Optional<CatalogEntity> optionalCatalog = Optional.of(catalogEntity);
when(catalogRepository.findByCode(any(String.class))).thenReturn(catalogEntity);
}
@Test
public void whenFindByCode() {
//Act
CatalogDto myCatalogDto = service.findByCode("code");
//Assert
assertTrue(myCatalogDto.getCode().equals("code"));
}
}
CatalogService
@Service
public class CatalogService {
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogService.class);
@Autowired
CatalogRepository catalogRepository;
@Autowired
CatalogMapper catalogMapper;
/**
*
* @param type
* @return catalog objects which type is type
*/
public List<CatalogDto> findByType(String type) {
LOGGER.info("Getting catalogs by type {}",type);
List<CatalogEntity> catalogsEntityList = catalogRepository.findByType(type);
List<CatalogDto> catalogDtoList = new ArrayList<>();
catalogsEntityList.forEach(catalogEntity -> {
catalogDtoList.add(catalogMapper.convertCatalogEntityToCatalogDto(catalogEntity));
});
return catalogDtoList;
}
/**
* Find catalog by code.
* @param code
* @return catalog
*/
public CatalogDto findByCode(String code) {
LOGGER.info("Getting catalogs by code {}",code);
return catalogMapper.convertCatalogEntityToCatalogDto(catalogRepository.findByCode(code));
}
}
CatalogMapper
@Component
public class CatalogMapper {
@Autowired
private modelmapper modelmapper;
/**
* Converts CatalogEntity object to CatalogDto object
* @param catalogEntity
* @return converted CatalogDto object
*/
public CatalogDto convertCatalogEntityToCatalogDto(CatalogEntity catalogEntity) {
return modelmapper.map(catalogEntity,CatalogDto.class);
}
}
CatalogRepository
@Repository
public interface CatalogRepository extends MongoRepository<CatalogEntity,String> {
List<CatalogEntity> findByType(String type);
CatalogEntity findByCode(String code);
}
问题
catalogRepository.findByCode(code)
正在按预期返回CatalogEntity对象,并且在执行返回空值的catalogMapper.convertCatalogEntityToCatalogDto(catalogRepository.findByCode(code));
后出现了问题。
我正在使用Intellij,这是恰好在执行catalogMapper.convertCatalogEntityToCatalogDto
函数之前的断点。
解决方法
catalogMapper是一个没有存根方法的模拟程序。
有几种方法可以修复您的测试:
选项1:仅测试与CatalogMapper的交互
在此选项中,您将呼叫catalogMapper.convertCatalogEntityToCatalogDto
存入存根。这是一个瘦单元测试,您仅测试与协作服务的交互。
正如您所说的,您要测试mapper的真实实现,有两种选择:
选项2:使用SpringBootTest
在此选项中,您依赖SpringBootTest来设置整个应用程序上下文。
您需要进行以下更改:
- 使用
@Autowired
而非@InjectMock
来使您的对象受测 - 使用
@MockBean
而非@Mock
进行存储库。SpringBootTest
忽略@Mock
。 - 摆脱其他模拟物
- 在创建整个应用程序上下文时,我将排除此选项,除非您的目标是进行全面集成测试(您从代码中的
@SpringBootTest
开始)
@SpringBootTest
public class CatalogServiceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Autowired
private CatalogService service;
@MockBean
CatalogRepository catalogRepository;
}
选项3:构建您自己需要的服务
- 摆脱
@SpringBootTest
- 仅模拟您要模拟的对象-存储库
- 为其他服务创建真实对象
- 您可能需要在服务中将字段注入更改为构造函数注入,这还是一个好主意
@Service
public class CatalogService {
final CatalogRepository catalogRepository;
final CatalogMapper catalogMapper;
@Autowired
public CatalogService(CatalogRepository catalogRepository,CatalogMapper catalogMapper) {
this.catalogRepository = catalogRepository;
this.catalogMapper = catalogMapper;
}
}
此方法仅创建测试所用的对象,而不是整个应用程序上下文,因此可能会导致对选项2进行更精简的测试。
@RunWith(MockitoJUnitRunner.class)
public class CatalogServiceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
private CatalogService service;
@Mock
CatalogRepository catalogRepository;
@Before
public void setUp() throws Exception {
var modelMapper = new ModelMapper();
var catalogMapper =new CatalogMapper(modelMapper);
service = new CatalogService(catalogRepository,catalogMapper);
CatalogEntity catalogEntity = new CatalogEntity();
catalogEntity.setId("id");
catalogEntity.setCode("code");
when(catalogRepository.findByCode(any(String.class))).thenReturn(catalogEntity);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。