【问题标题】:How i am must test this method with mockito?我必须如何用 mockito 测试这个方法?
【发布时间】:2019-04-29 15:28:09
【问题描述】:

服务类中的方法:

@Override
@Transactional(readOnly = true)
public Collection<Account> searchAccounts(String partOfName) {
    Collection<Account> accounts = accountDao.getAll();
    CollectionUtils.filter(accounts, account ->
            account.getName().toLowerCase().contains(partOfName.toLowerCase()) ||
                    account.getSurname().toLowerCase().equalsIgnoreCase(partOfName.toLowerCase()));
    return accounts;
}

我不明白我必须对 CollectionUtils.filter 做什么。也嘲笑这个? 现在我在测试类中有这个:

@Test
public void searchAccountsByPartOfName() {
    service.searchAccounts("test");
    verify(accountDao, times(1)).getAll();
}

【问题讨论】:

  • 你不需要模拟CollectionUtils.filter()。但是,您可能需要模拟accountDao,这样当您调用它的getAll() 方法时,您会得到一个Accounts 的集合。
  • @ChocolateAndCheese 实际程序中CollectionUtils.filter后账号收藏可能会改变,没关系?
  • 这正是您要测试的内容,对吧?您正在尝试测试您的过滤方法是否有效,因此预计CollectionUtils.filter() 将修改返回的Collection

标签: java testing mocking mockito


【解决方案1】:

CollectionUtils.filter 是一种基于谓词过滤集合的实用方法。你不需要嘲笑它。

您需要做的是模拟accountDao 以返回Collection&lt;Account&gt;。集合中的帐户实例可以是真实对象或模拟对象。如果它是一个简单的 POJO,我建议创建一个真实 Account 对象的列表。

然后,您验证从列表中返回的 Collection&lt;Account&gt;,因为它根据谓词正确过滤掉了 Account 对象。

有了这个,你正在测试你的代码/逻辑的症结。

它可能看起来像这样(免责声明:未编译)

@Test
public void searchAccountsByPartOfName() throws ParseException {
    Collection<Account> accounts = new ArrayList<>();
    Account acc1 = new new Account(..); //name having the substring "test"
    Account acc2 = new new Account(..); //surname equals "test"
    Account acc3 = new new Account(..);  //neither name nor surname has the substring "test"
    accounts.add(acc1); 
    accounts.add(acc2); 
    accounts.add(acc3);

    when(accountDao.getAll()).thenReturn(accounts);

    service.searchAccounts("test");

    Collection<Account> actual = service.searchAccounts("test");

    //here assert that the actual is of size 2 and it has the ones that pass the predicate
    assertEquals(2, actual.size());
    assertEquals(acc1, actual.get(0));
    assertEquals(acc2, actual.get(1));
}

您可能还想编写类似的测试来测试不区分大小写的检查。

【讨论】:

  • @diofloyk 最初我认为它会删除通过谓词的那些。但它恰恰相反。我已经更新了答案
  • 您好 user7,只是一个旁注:一般来说assertEquals(acc1, actual.get(0)); 不一定是执行断言的最佳方式。 AssertJ/Hamcrest 旨在解决这一点。你有我的投票权。
  • @davidxxx 你的意思是使用 assertEquals 传递预期的集合吗?
  • 不,我的意思是Assertions.assertThat(actual ).extracting(Account::getName, Account::getSurname).containsExactly(tuple(acc1.getName(), acc1.getSurname()), tuple(acc2.getName(), acc2.getSurname())) 查看joel-costigliola.github.io/assertj/… 中的“关于提取的可迭代/数组元素的属性/字段的断言”。所有这些都使您可以将 equals() 与两个不同的东西的断言结合起来。
  • @davidxxx 谢谢你的注意和回答,看起来很有用。
【解决方案2】:

CollectionUtils.filter() 调用包含由searchAccounts() 方法执行的逻辑,而Collection&lt;Account&gt; accounts = accountDao.getAll();searchAccounts() 的一部分,您希望将其隔离为由另一个依赖项执行。
因此模拟accountDao() 以返回特定的帐户列表并断言searchAccounts() 返回预期的过滤帐户。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 2015-04-07
    • 1970-01-01
    相关资源
    最近更新 更多