通常,好的软件工程实践一定少不了单元测试,以此来保证程序的行为与预期一致。通过测试用例确保代码中的每个组成部分都实现预期的结果。如下:
public class Point{
private final int x;
private final int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
public Point moveRightBy(int x){ return new Point(this.x + x, this.y); }
}
@Test
public void testMoveRightBy() throws Exception {
Point p1 = new Point(5, 5);
Point p2 = p1.moveRightBy(10);
assertEquals(15, p2.getX());
assertEquals(5, p2.getY());
}
1、测试可见Lambda函数的行为
对于public生明的方法,可以在用例内部完成测试,测试工作相对容易。但是Lambda函数并无函数名,要想对它们进行测试会比较困难,因为你无法通过函数名的方式调用它们。
有时可以借助某个字段访问Lambda函数,此时可以利用这些字段,通过它们对封装在Lambda函数内的逻辑进行测试。比如假设在Point类中添加了静态字段compareByXAndThenY,通过该字段,使用方法引用可以访问Comparator对象:
public class Point{
public final static Comparator
comparing(Point::getX).thenComparing(Point::getY);
…
}
Lambda表达式会生成函数接口的一个实例,因此可以测试该实例的行为。我们可以使用不同的参数,对Comparator对象类型实例compareByXAndThenY的compare方法进行调用,验证它们的行为是否符合预期:
@Test
public void testComparingTwoPoints() throws Exception {
Point p1 = new Point(10, 15);
Point p2 = new Point(10, 20);
int result = Point.compareByXAndThenY.compare(p1 , p2);
assertEquals(-1, result);
}
2、测试使用Lambda方法的行为
Lambda的初衷是将一部分逻辑封装起来给另一个方法使用。因此,不应将Lambda表达式声明为public,它们仅是具体的实现细节。相反,我们需要对使用Lambda表达式的方法进行测试。
public static List
return points.stream()
.map(p -> new Point(p.getX() + x, p.getY()))
.collect(toList());
}
上述代码中,我们没必要对Lambda表达式p -> new Point(p.getX() + x,p.getY())进行测试,它只是moveAllPointsRightBy内部的实现细节,我们更应关注的是moveAllPointsRightBy方法的行为:
@Test
public void testMoveAllPointsRightBy() throws Exception{
List
List
List
assertEquals(expectedPoints, newPoints);
}
3、将复杂的Lambda表达式分到不同的方法
可能会碰到非常复杂的Lambda表达式,包含大量的业务逻辑,比如需要处理复杂情况的计价算法,从而导致无法在测试程序中引用Lambda表达式。
一种解决策略是将Lambda表达式转换为方法引用(往往需要声明一个新的常规方法),然后可以用常规的方式对新的方法进行测试。
4、高阶函数的测试
接受函数作为参数的方法或者返回一个函数的方法(所谓的“高阶函数”,higher-order function)更难测试。如果一个方法接受Lambda表达式作为参数, 可采用的一个方案是使用不同的Lambda表达式对它进行测试。如下:
@Test
public void testFilter() throws Exception{
List
List
List
assertEquals(Arrays.asList(2, 4), even);
assertEquals(Arrays.asList(1, 2), smallerThanThree);
}
如果被测试方法的返回值是另一个方法,可以仿照之前处理Comparator的方法,把它当成一个函数接口,对它的功能进行测试。
--参考文献《Java8实战》