![](/img/trans.png)
[英]Spring Data JPA Specifications AND operation of predicates unit test not excepted or covered
[英]how to unit test method using “Spring Data JPA” Specifications
我正在玩org.springframework.data.jpa.domain.Specifications,它只是一个基本的搜索:
public Optional<List<Article>> rechercheArticle(String code, String libelle) {
List<Article> result = null;
if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(libelle)){
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
}else{
if(StringUtils.isNotEmpty(code)){
result= articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)));
}else{
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteLibelle(libelle)));
}
}
if(result.isEmpty()){
return Optional.empty();
}else{
return Optional.of(result);
}
}
这实际上工作正常,但我想为这个方法编写单元测试,我无法弄清楚如何检查传递给我的articleRepository.findAll()的规范
目前我的单元测试看起来像:
@Test
public void rechercheArticle_okTousCriteres() throws FacturationServiceException {
String code = "code";
String libelle = "libelle";
List<Article> articles = new ArrayList<>();
Article a1 = new Article();
articles.add(a1);
Mockito.when(articleRepository.findAll(Mockito.any(Specifications.class))).thenReturn(articles);
Optional<List<Article>> result = articleManager.rechercheArticle(code, libelle);
Assert.assertTrue(result.isPresent());
//ArgumentCaptor<Specifications> argument = ArgumentCaptor.forClass(Specifications.class);
Mockito.verify(articleRepository).findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
//argument.getValue().toPredicate(root, query, builder);
}
任何想法?
我遇到了几乎和你一样的问题,并且我将包含规范的类更改为一个对象而不是一个静态方法的类。 这样我就可以轻松地模拟它,使用依赖注入来传递它,并测试调用哪些方法(不使用PowerMockito来模拟静态方法)。
如果你想像我一样做,我建议你用集成测试测试规范的正确性,其余的,只要调用正确的方法。
例如:
public class CdrSpecs {
public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) {
return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end);
}
}
然后,您对此方法进行了集成测试,该测试将测试该方法是否正确:
@RunWith(SpringRunner.class)
@DataJpaTest
@Sql("/cdr-test-data.sql")
public class CdrIntegrationTest {
@Autowired
private CdrRepository cdrRepository;
private CdrSpecs specs = new CdrSpecs();
@Test
public void findByPeriod() throws Exception {
LocalDateTime today = LocalDateTime.now();
LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth));
assertThat(cdrList).isNotEmpty().hasSize(2);
}
现在,当您想要对其他组件进行单元测试时,您可以像这样进行测试,例如:
@RunWith(JUnit4.class)
public class CdrSearchServiceTest {
@Mock
private CdrSpecs specs;
@Mock
private CdrRepository repo;
private CdrSearchService searchService;
@Before
public void setUp() throws Exception {
initMocks(this);
searchService = new CdrSearchService(repo, specs);
}
@Test
public void testSearch() throws Exception {
// some code here that interact with searchService
verify(specs).calledBetween(any(LocalDateTime.class), any(LocalDateTime.class));
// and you can verify any other method of specs that should have been called
}
当然,在服务内部,您仍然可以使用规范类的where 和 static方法。
我希望这可以帮到你。
如果你正在编写单元测试,那么你或许应该嘲笑到呼叫findAll()
的方法articleRepository
使用像嘲弄的框架类Mockito
或PowerMock
。
有一个方法verify()
,您可以使用它来检查是否为特定参数调用了mock。
例如,如果您正在articleRepository
类的findAll()
方法,并想知道是否使用特定参数调用此方法,那么您可以执行以下操作:
Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);
如果没有为您提供的参数调用mock,则测试将失败。
你的问题是你在这个方法中做了太多事情。 您应该有三种不同的方法可以在articleRepository上运行。
然后你可以像其他人建议的那样使用模拟:
请注意:这三种方法应该是内部的; 主要观点是:你无法通过外部的一个电话来测试这种方法; 因为它不止一件事,取决于您提供的输入。 因此,您需要为代码中的每个潜在路径创建至少一个测试方法。 当您将代码分成不同的方法时,这会变得更容易(从概念的角度来看)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.