簡體   English   中英

如何使用“Spring Data JPA”規范進行單元測試方法

[英]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使用像嘲弄的框架類MockitoPowerMock

有一個方法verify() ,您可以使用它來檢查是否為特定參數調用了mock。

例如,如果您正在articleRepository類的findAll()方法,並想知道是否使用特定參數調用此方法,那么您可以執行以下操作:

Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);

如果沒有為您提供的參數調用mock,則測試將失敗。

你的問題是你在這個方法中做了太多事情。 您應該有三種不同的方法可以在articleRepository上運行。

然后你可以像其他人建議的那樣使用模擬:

  • 設置你的模擬,以便你知道應該在articleRepository上調用哪個
  • 驗證確切的預期呼叫正在發生

請注意:這三種方法應該是內部的; 主要觀點是:你無法通過外部的一個電話來測試這種方法; 因為它不止一件事,取決於您提供的輸入。 因此,您需要為代碼中的每個潛在路徑創建至少一個測試方法。 當您將代碼分成不同的方法時,這會變得更容易(從概念的角度來看)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM