使用 JUnit 测试带有 if/else 语句的 void 方法莫基托

发布于 2025-01-18 17:15:29 字数 2869 浏览 0 评论 0原文

使用Juinit 5和Mockito测试方法的正确方法是什么?我发现了两个测试用例,当Artmerk阵列大小为零时,并且当大于零时,但是在第二种情况下,我无法验证Artmerkrepository.save(tosave)和artmerkrepository.deleteinbatch(oldlist)这两个方法。

@Service 
public class ItemService{

   @Autowired
   ArtMerkRepository artMerkRepository;

   @Autowired 
   ItemServiceRestClient itemServiceRestClient;

   public void updateOrInsertArtMerk(String artNr) {
    LOGGER.info("Start saving ArtMerk.");
    ArtMerk[] artMerk = itemServiceRestClient.getArtMerk(artNr);
    if(artMerk != null) {
        if(artMerk.length == 0) {
            artMerkRepository.deleteByArtNr(artNr);
        }else {
            for (ArtMerk a : artMerk) {
                List<ArtMerk> aExists = artMerkRepository.findByArtNr(a.getArtNr());
                ArtMerk toSave = (aExists != null && !aExists.isEmpty()) ? UpdateUtils.updateArtMerk(aExists.get(0), a) : a;
                artMerkRepository.save(toSave);
            }
            List<ArtMerk> newList = new ArrayList<>(Arrays.asList(artMerk.clone()));
            List<ArtMerk> oldList = new ArrayList<>(artMerkRepository.findByArtNr(artNr));
            oldList.removeAll(newList);
            if (oldList != null && oldList.size() > 0) {
                artMerkRepository.deleteInBatch(oldList);
            }
        }
    }
    LOGGER.info("Successful update of ArtMerk.");
}

}

我的测试方法看起来像这样:

@Test
void updateOrInsertArtMerk_whenArtMerkArrSizeIsNotZero() {
    //given
    String artNr = "0001";
    ArtMerk artMerk1 = new ArtMerk();
    artMerk1.setArtNr(artNr);
    ArtMerk artMerk2 = new ArtMerk();
    artMerk2.setArtNr(artNr);
    List<ArtMerk> oldList = Arrays.asList(artMerk1, artMerk2);
    ArtMerk[] artMerks = new ArtMerk[]{artMerk1};

    //when
    when(itemServiceRestClient.getArtMerk(artNr)).thenReturn(artMerks);
    when(artMerkRepository.findByArtNr(artNr)).thenReturn(Arrays.asList(artMerks));
    when(artMerkRepository.save(artMerk1)).thenReturn(artMerk1);
    when(artMerkRepository.findByArtNr(artNr)).thenReturn(oldList);
    doNothing().when(artMerkRepository).deleteInBatch(oldList);

    //then
    itemService.updateOrInsertArtMerk(artNr);
    verify(artMerkRepository, times(2)).findByArtNr(artNr);
    verify(artMerkRepository, times(1)).save(artMerk1);
    verify(artMerkRepository,  times(1)).deleteInBatch(oldList);
}

@Test
void updateOrInsertArtMerk_whenArtMerkArrSizeIsZero() {
    //given
    String artNr = "0001";
    ArtMerk[] artMerks = new ArtMerk[]{};

    //when
    when(itemServiceRestClient.getArtMerk(artNr)).thenReturn(artMerks);
    doNothing().when(artMerkRepository).deleteByArtNr(artNr);

    //then
    itemService.updateOrInsertArtMerk(artNr);
    verify(artMerkRepository, times(1)).deleteByArtNr(artNr);
}

第一个测试方法由于不必要的刺激性而失败。

What is correct way to test method like this, using JUinit 5 and Mockito ? I found two test cases, when artMerk array size is zero, and when is greater than zero, but in second case, I couldn't verify that both method artMerkRepository.save(toSave) and artMerkRepository.deleteInBatch(oldList) are called.

@Service 
public class ItemService{

   @Autowired
   ArtMerkRepository artMerkRepository;

   @Autowired 
   ItemServiceRestClient itemServiceRestClient;

   public void updateOrInsertArtMerk(String artNr) {
    LOGGER.info("Start saving ArtMerk.");
    ArtMerk[] artMerk = itemServiceRestClient.getArtMerk(artNr);
    if(artMerk != null) {
        if(artMerk.length == 0) {
            artMerkRepository.deleteByArtNr(artNr);
        }else {
            for (ArtMerk a : artMerk) {
                List<ArtMerk> aExists = artMerkRepository.findByArtNr(a.getArtNr());
                ArtMerk toSave = (aExists != null && !aExists.isEmpty()) ? UpdateUtils.updateArtMerk(aExists.get(0), a) : a;
                artMerkRepository.save(toSave);
            }
            List<ArtMerk> newList = new ArrayList<>(Arrays.asList(artMerk.clone()));
            List<ArtMerk> oldList = new ArrayList<>(artMerkRepository.findByArtNr(artNr));
            oldList.removeAll(newList);
            if (oldList != null && oldList.size() > 0) {
                artMerkRepository.deleteInBatch(oldList);
            }
        }
    }
    LOGGER.info("Successful update of ArtMerk.");
}

}

My test methods looks like this:

@Test
void updateOrInsertArtMerk_whenArtMerkArrSizeIsNotZero() {
    //given
    String artNr = "0001";
    ArtMerk artMerk1 = new ArtMerk();
    artMerk1.setArtNr(artNr);
    ArtMerk artMerk2 = new ArtMerk();
    artMerk2.setArtNr(artNr);
    List<ArtMerk> oldList = Arrays.asList(artMerk1, artMerk2);
    ArtMerk[] artMerks = new ArtMerk[]{artMerk1};

    //when
    when(itemServiceRestClient.getArtMerk(artNr)).thenReturn(artMerks);
    when(artMerkRepository.findByArtNr(artNr)).thenReturn(Arrays.asList(artMerks));
    when(artMerkRepository.save(artMerk1)).thenReturn(artMerk1);
    when(artMerkRepository.findByArtNr(artNr)).thenReturn(oldList);
    doNothing().when(artMerkRepository).deleteInBatch(oldList);

    //then
    itemService.updateOrInsertArtMerk(artNr);
    verify(artMerkRepository, times(2)).findByArtNr(artNr);
    verify(artMerkRepository, times(1)).save(artMerk1);
    verify(artMerkRepository,  times(1)).deleteInBatch(oldList);
}

@Test
void updateOrInsertArtMerk_whenArtMerkArrSizeIsZero() {
    //given
    String artNr = "0001";
    ArtMerk[] artMerks = new ArtMerk[]{};

    //when
    when(itemServiceRestClient.getArtMerk(artNr)).thenReturn(artMerks);
    doNothing().when(artMerkRepository).deleteByArtNr(artNr);

    //then
    itemService.updateOrInsertArtMerk(artNr);
    verify(artMerkRepository, times(1)).deleteByArtNr(artNr);
}

And first test method fails because of UnnecessaryStubbingException.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

李白 2025-01-25 17:15:30

您应该通过构造函数注入它们,而不是

   @Autowired

您的依赖性。

这样,您可以在测试期间注入模拟对象,而不是使用类似

verify(<mocked object>, times(1)).<mocked method>(argumentCaptor.capture());

Instead of

   @Autowired

your dependencies, you should inject them via a constructor.

This way, you can inject during test a mock object and than use something like

verify(<mocked object>, times(1)).<mocked method>(argumentCaptor.capture());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文