【问题标题】:How to test if the correct lambda value was passed as an argument (with Mockito)?如何测试是否将正确的 lambda 值作为参数传递(使用 Mockito)?
【发布时间】:2018-10-23 09:46:31
【问题描述】:

我有这个功能:

public class Cache {
    (...)
    public void removeAllIf(Predicate<Product> predicate) {
        (...)
    }
}

我打电话给productsCache.removeAllIf(Product::isChecked);

目前我用

测试它

then(productsCache).should().removeAllIf(any(Predicate.class));

但这并不准确(不测试传递的 lambda 是否为 Product::isChecked)。第二个问题是我收到 lint 消息:Unchecked assignment.

有更好的解决方案吗?

已编辑:

我不想测试removeAllIf 函数实现。我想测试是否使用正确的参数调用了removeAllIf

要测试的场景:

public class Repository {
    public void removeCheckedProducts() {
        remoteDataSource.removeCheckedProducts();
        localDataSource.removeCheckedProducts();
        cache.removeAllIf(Product::isChecked);

    }
}

单元测试:

@Test
public void removeCheckedProducts() {

    //when
    repository.removeCheckedProducts();

    //then
    then(remoteDataSource).should().removeCheckedProducts();
    then(localDataSource).should().removeCheckedProducts();
    then(cache).should().removeAllIf(any(Predicate.class));


}

【问题讨论】:

  • 向我展示您与此场景相关的所有逻辑? removeAllIf方法的实现和Product类结构传入的谓词。
  • 你应该关注Product.isChecked的定义来对其进行单元测试。
  • 我正在测试是否调用了 removeAllIf,而不是 Product.isChecked 的实现。请检查我的编辑。
  • 如果调用者的源代码看起来像removeAllIf(Product::isChecked),那么编写测试代码来验证这段微不足道的代码是否真正使用参数Product::isChecked调用removeAllIf是一种资源浪费。你应该专注于测试调用代码是否做了它应该做的事情(好吧,好吧,如果调用者是一个名为 callTheMethodRemoveAllIfWithProductIsChecked 的方法并且它的文档说“这个方法的唯一目的是调用 removeAllIf论点Product::isChecked”,那么,你就在正确的道路上)。

标签: java unit-testing lambda java-8 mockito


【解决方案1】:

你可以使用 ArgumentCaptor

@Captor
  ArgumentCaptor<Predicate> captor = ArgumentCaptor.forClass(Predicate.class);;

@Test
public void removeCheckedProducts() {

    //when
    repository.removeCheckedProducts();

    //then
    then(remoteDataSource).should().removeCheckedProducts();
    then(localDataSource).should().removeCheckedProducts();
    then(cache).should().removeAllIf(captor.capture());
    Predicate t = Product.checkPredicate();
    assertSame(t,captor.getValue());



}

【讨论】:

  • assertSame 不起作用,Object 不是功能接口。
  • 将谓词赋值给变量,可以比较。请注意,为了能够比较谓词是否相等,您必须将谓词分配给变量并重用此谓词,否则您将始终创建新的 Lambda。因此,如果您想测试是否完全相等,产品应该具有始终返回相同谓词/lambda 的方法。如果您无法缓存 lambda,则可以检查 lambda 类的 toString 并检查它是否来自 Product 类。
【解决方案2】:

您可以检查 removeAllIf 参数行为而不是相等性。

Predicate<Product> removeAllIfArgument = mockingDetails(cache).getInvocations()
        .iterator()
        .next()
        .getArgument(0);

Product checkedProduct = mock(Product.class);
Product uncheckedProduct = mock(Product.class);
given(checkedProduct.isChecked()).willReturn(true);
given(uncheckedProduct.isChecked()).willReturn(false);

assertTrue(removeAllIfArgument.test(checkedProduct));
assertFalse(removeAllIfArgument.test(uncheckedProduct));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2019-11-30
    • 2018-01-27
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多