Java8学习笔记之测试Lambda表达式

通常,好的软件工程实践一定少不了单元测试,以此来保证程序的行为与预期一致。通过测试用例确保代码中的每个组成部分都实现预期的结果。如下:

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 compareByXAndThenY =

        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 moveAllPointsRightBy(List points, int x){

    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 points = Arrays.asList(new Point(5, 5), new Point(10, 5));

    List expectedPoints = Arrays.asList(new Point(1, 5), new Point(2, 5));

    List newPoints = Point.moveAllPointsRightBy(points, 10);

    assertEquals(expectedPoints, newPoints);

}

3、将复杂的Lambda表达式分到不同的方法

可能会碰到非常复杂的Lambda表达式,包含大量的业务逻辑,比如需要处理复杂情况的计价算法,从而导致无法在测试程序中引用Lambda表达式。

一种解决策略是将Lambda表达式转换为方法引用(往往需要声明一个新的常规方法),然后可以用常规的方式对新的方法进行测试。

4、高阶函数的测试

接受函数作为参数的方法或者返回一个函数的方法(所谓的“高阶函数”,higher-order function)更难测试。如果一个方法接受Lambda表达式作为参数, 可采用的一个方案是使用不同的Lambda表达式对它进行测试。如下:

@Test

public void testFilter() throws Exception{

    List numbers = Arrays.asList(1, 2, 3, 4);

    List even = filter(numbers, i -> i % 2 == 0);

    List smallerThanThree = filter(numbers, i -> i < 3);

    assertEquals(Arrays.asList(2, 4), even);

    assertEquals(Arrays.asList(1, 2), smallerThanThree);

}

如果被测试方法的返回值是另一个方法,可以仿照之前处理Comparator的方法,把它当成一个函数接口,对它的功能进行测试。


--参考文献《Java8实战》

你可能感兴趣的:(Java8学习笔记之测试Lambda表达式)