我一直在使用
Java 8几个月,我已经开始使用Lambda表达式,这在某些情况下非常方便.然而,我经常碰到一些问题来单元测试使用Lambda的代码.
以下列伪代码为例:
private Bar bar; public void method(int foo){ bar.useLambda(baz -> baz.setFoo(foo)); }
一种方法是在酒吧上验证通话
verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());
但是,通过这样做,我不会测试Lambda的代码.
还要注意,我不能用一个方法和使用方法引用来替换Lambda:
bar.useLambda(This::setFooOnBaz);
因为我不会有这个方法的foo.或至少这就是我的想法.
你以前有这个问题吗?我如何测试或重构我的代码来正确测试?
编辑
由于我编码是一个单元测试,我不想实例化吧,而我将使用模拟.所以我不能只是验证baz.setFoo调用.
解决方法
你不能直接单元测试一个lambda,因为它没有一个名字.除非你有参考,否则没有办法调用它.
通常的替代方案是将lambda重构为命名方法,并使用产品代码中的方法引用,并从测试代码中以名称调用该方法.如你所说,这种情况不能以这种方式重构,因为它捕获到foo,而唯一可以通过方法引用来捕获的就是接收器.
但是,answer from yshavit涉及到是否有必要对私人方法进行单元测试.一个lambda可以被认为是私有的方法.
这里也有一个更大的一点.单元测试的其中一个原因是您不需要对too simple to break进行单元测试.这与lambda的理想情况非常吻合,这是一个非常简单的表达式,这显然是正确的. (至少这就是我认为的理想.)考虑一下这个例子:
baz -> baz.setFoo(foo)
毫无疑问,这个lambda表达式,当提交一个Baz引用时,会调用它的setFoo方法并将其作为参数传递给foo?也许这么简单,它不需要进行单元测试.
另一方面,这只是一个例子,也许你想要测试的实际的lambda比较复杂.我看到使用大型,嵌套,多行lambdas的代码.参见this answer及其问题和其他答案,例如.这样的羔羊确实很难进行调试和测试.如果lambda中的代码足够复杂,以至于需要进行测试,那么该代码应该从lambda中重构出来,以便可以使用常规技术进行测试.