![](/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.