Java 8 Lambdas的单元测试代码 [英] Unit test code with Java 8 Lambdas

查看:242
本文介绍了Java 8 Lambdas的单元测试代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用Java 8几个月了,并且我开始使用Lambda表达式,这在某些情况下非常方便.但是,我经常遇到一些问题,以对使用Lambda的代码进行单元测试.

I have been using Java 8 for some months, and I have started to use Lambda expressions, which are very convenient for some cases. However, I often come across some problems to unit test the code that uses a Lambda.

以下面的伪代码为例:

private Bar bar;

public void method(int foo){
    bar.useLambda(baz -> baz.setFoo(foo));
}

一种方法是只验证bar上的通话

One approach would be to just verify the call on bar

verify(bar).useLambda(Matchers.<Consumer<Baz>>.any());

但是,这样做不会测试Lambda的代码.

But, by doing that, I don't test Lambda's code.

还请注意,我无法使用方法替换Lambda并使用方法参考:

Also note that I am not able to replace the Lambda with a method and use method reference:

bar.useLambda(This::setFooOnBaz);

因为我在该方法上没有foo. 或者至少我是这样认为的.

Because I will not have the foo on that method. Or at least that is what I think.

您以前遇到过此问题吗?如何测试或重构代码以对其进行正确测试?

修改

由于我要编码的是单元测试,所以我不想实例化bar,而我将使用模拟代替.因此,我将无法仅验证baz.setFoo调用.

Since what I am coding is an unit test, I don't want to instantiate bar, and I will be using a mock instead. So I will not be able to just verify the baz.setFoo call.

推荐答案

您不能直接对lambda进行单元测试,因为它没有名称.除非您有对其的引用,否则无法调用它.

You can't unit test a lambda directly, since it doesn't have a name. There's no way to call it unless you have a reference to it.

通常的替代方法是将lambda重构为命名方法,并使用产品代码中的方法引用,然后从测试代码中按名称调用该方法.如您所述,这种情况无法通过这种方式重构,因为它捕获了foo,并且方法引用唯一可以捕获的是接收器.

The usual alternative is to refactor the lambda into a named method and use a method reference from product code and call the method by name from test code. As you note, this case can't be refactored this way because it captures foo, and the only thing that can be captured by a method reference is the receiver.

但是yshavit的答案谈到了一个重要的问题,即是否有必要对私有方法进行单元测试. Lambda当然可以视为私有方法.

But the answer from yshavit touches upon an important point about whether it's necessary to unit test private methods. A lambda can certainly be considered a private method.

这里还有一个更大的要点.单元测试的原则之一是,您不需要对太简单的东西进行单元测试.休息.这与lambda的理想情况非常吻合,该表达式非常简单,显然是正确的. (至少,这就是我认为的理想选择.)请考虑以下示例:

There's a larger point here too. One of the priciples of unit testing is that you don't need to unit test anything that's too simple to break. This aligns well with the ideal case for lambda, which is an expression that's so simple it's obviously correct. (At least, that's what I consider ideal.) Consider the example:

    baz -> baz.setFoo(foo)

是否有疑问,当此lambda表达式传递给Baz引用时,将调用其setFoo方法并将其作为参数传递给foo?也许它是如此简单以至于不需要进行单元测试.

Is there any doubt that this lambda expression, when handed a Baz reference, will call its setFoo method and pass it foo as an argument? Maybe it's so simple that it doesn't need to be unit tested.

另一方面,这仅是示例,也许您想要测试的实际lambda相当复杂.我看过使用大型嵌套多行lambda的代码.例如,请参见此答案及其问题和其他答案.这样的lambda确实很难调试和测试.如果lambda中的代码足够复杂以至于需要进行测试,那么也许应该将该代码重构出lambda,以便可以使用常规技术对其进行测试.

On the other hand, this is merely an example, and maybe the actual lambda you want to test is considerably more complicated. I've seen code that uses large, nested, multi-line lambdas. See this answer and its question and other answers, for example. Such lambdas are indeed difficult to debug and test. If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.

这篇关于Java 8 Lambdas的单元测试代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆