Verify That Lambda Expression Was Called Using Mockito – 使用 Mockito 验证是否调用了 Lambda 表达式

最后修改: 2023年 12月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll look at how we can test that our code calls a lambda function. There are two approaches to achieving this goal to consider. We’ll first check that the lambda is invoked with the correct arguments. Then, we’ll look at testing the behavior instead and checking if the lambda code has executed and produced the expected result.

在本教程中,我们将了解如何测试我们的代码是否调用了 lambda 函数。要实现这一目标,我们需要考虑两种方法。首先,我们将检查 lambda 是否以正确的参数被调用。然后,我们将测试行为,检查 lambda 代码是否已执行并产生预期结果。

2. Example Class Under Test

2.受测班级示例

To start, let’s create a class LambdaExample that has an ArrayList we’ll call bricksList:

首先,让我们创建一个 LambdaExample 类,该类有一个 ArrayList 我们将其称为 bricksList

class LambdaExample {
    ArrayList<String> bricksList = new ArrayList<>();
}

Now, let’s add an inner class called BrickLayer, which will be able to add bricks for us:

现在,让我们添加一个名为 BrickLayer 的内部类,它将能够为我们添加砖块:

class LambdaExample {

    BrickLayer brickLayer = new BrickLayer();

    class BrickLayer {
        void layBricks(String bricks) {
            bricksList.add(bricks);
        }
    }
}

BrickLayer doesn’t do much. It has a single method, layBricks() that will add a brick to our List for us. This could have been an external class, but to keep the concepts together and simple an inner class works here.

BrickLayer 并没有做什么。它只有一个方法,layBricks(),可以为我们添加一块砖到 List 中。这本可以是一个外部类,但为了保持概念的统一和简单,这里可以使用一个内部类。

Finally, we can add a method to LambdaExample to call layBricks() via a lambda:

最后,我们可以为 LambdaExample 添加一个方法,通过 lambda 调用 layBricks()

void createWall(String bricks) {
    Runnable build = () -> brickLayer.layBricks(bricks);
    build.run();
}

Again, we’ve kept things simple. Our real-world applications are more complex but this streamlined example will help explain the test methods.

同样,我们将事情简单化。我们在现实世界中的应用更为复杂,但这个精简的示例将有助于解释测试方法。

In the upcoming sections, we’ll test whether calling createWall() results in the expected execution of layBricks() within our lambda.

在接下来的章节中,我们将测试调用 createWall() 是否会在 lambda 中执行 layBricks() 的预期结果。

3. Testing Correct Invocation

3.测试调用是否正确

The first testing method we’ll look at is based on confirming that the lambda is called when we expect it. Furthermore, we’ll need to confirm that it received the correct arguments. To start we’ll need to create Mocks of both BrickLayer and LambdaExample:

我们要了解的第一种测试方法基于确认 lambda 是否在我们期望的时候被调用。此外,我们还需要确认它是否收到了正确的参数。首先,我们需要创建 MocksBrickLayerLambdaExample:</em

@Mock
BrickLayer brickLayer;
@InjectMocks
LambdaExample lambdaExample;

We’ve applied the @InjectMocks annotation to LambdaExample so that it uses the mocked BrickLayer object. We’ll be able to confirm the call to the layBricks() method because of this.

我们已将 @InjectMocks 注解应用到 LambdaExample 中,因此它使用了模拟的 BrickLayer 对象。因此,我们将能够确认对 layBricks() 方法的调用。

We can now write our test:

现在我们可以编写测试了:

@Test
void whenCallingALambda_thenTheInvocationCanBeConfirmedWithCorrectArguments() {
    String bricks = "red bricks";
    lambdaExample.createWall(bricks);
    verify(brickLayer).layBricks(bricks);
}

In this test, we’ve defined the String we want to add to bricksList and passed it as an argument to createWall(). Let’s keep in mind that we’re using the Mock we created earlier as the instance of LambdaExample.

在此测试中,我们定义了要添加到 bricksList 中的 String 并将其作为参数传递给 createWall() 。请记住,我们正在使用之前创建的 Mock 作为 LambdaExample 的实例。

We’ve then used Mockitos verify() function. Verify() is hugely helpful for this kind of test. It confirms the function layBricks() was called and that the argument was what we expected.

然后,我们使用了 Mockitos verify() 函数。Verify()对此类测试大有帮助。它可以确认函数 layBricks() 已被调用,并且参数与我们预期的一致。

There’s much more we can do with verify(). For example, confirming how many times a method is called. For our purposes, however, it’s sufficient to confirm that our lambda invoked the method as expected.

我们还可以使用 verify() 做更多事情。 例如,确认一个方法被调用了多少次。不过,就我们的目的而言,确认我们的 lambda 按预期调用了方法就足够了。

4. Testing Correct Behaviour

4.测试正确行为

The second route we can go down for testing is to not worry about what gets called and when. Instead, we’ll confirm that the expected behavior of the lambda function occurs. There will almost always be a good reason we’re calling a function. Perhaps to perform a calculation or to get or set a variable.

我们可以采用的第二种测试方法是,不必担心调用的内容和时间。相反,我们将确认 lambda 函数的预期行为是否发生。我们调用函数几乎总是有充分的理由。也许是为了执行计算,也许是为了获取或设置变量。

In our example, the lambda adds a given String to an ArrayList. In this section, let’s verify that the lambda successfully executes that task:

在我们的示例中,lambda 将给定的 String 添加到 ArrayList 中。在本节中,我们将验证 lambda 是否成功执行了该任务:

@Test
void whenCallingALambda_thenCorrectBehaviourIsPerformed() {
    LambdaExample lambdaExample = new LambdaExample();
    String bricks = "red bricks";
        
    lambdaExample.createWall(bricks);
    ArrayList<String> bricksList = lambdaExample.getBricksList();
        
    assertEquals(bricks, bricksList.get(0));
}

Here, we’ve created an instance of the LambdaExample class. Next, we’ve called createWall() to add a brick to the ArrayList.

在这里,我们创建了一个 LambdaExample 类的实例。接下来,我们调用 createWall()ArrayList 添加一块砖。

We should now see that bricksList contains the String we just added. Assuming the code correctly executes the lambda. We confirmed that by retrieving bricksList from lambdaExample and checking the contents.

现在我们应该看到 bricksList 包含了我们刚刚添加的 String 。假设代码正确执行了 lambda。我们通过从 lambdaExample 中检索 bricksList 并检查其内容来确认这一点。

We can conclude that the lambda is executing as expected, as that’s the only way our String could have ended up in the ArrayList.

我们可以得出结论,lambda 正在按预期执行,因为这是 String 最终进入 ArrayList 的唯一途径。

5. Conclusion

5.结论

In this article, we’ve looked at two methods for testing lambda calls. The first is useful when we can mock the class containing the function and inject it into the class which calls it as a lambda. In that case, we can use Mockito to verify the call to the function and the correct arguments. This offers no confidence that the lambda went on to do what we expected, however.

在本文中,我们介绍了两种测试 lambda 调用的方法。第一种方法非常有用,我们可以模拟包含函数的类,并将其注入作为 lambda 调用函数的类中。在这种情况下,我们可以使用 Mockito 来验证函数的调用和参数的正确性。不过,这并不能保证 lambda 会按照我们的预期运行。

The alternative is to test that the lambda produces the expected results when called. This offers more test coverage and is often preferable if it’s simple to access and confirm the correct behavior of the function call.

另一种方法是测试 lambda 在调用时是否产生预期结果。如果访问和确认函数调用行为的正确性很简单,这种方法的测试覆盖面更大,通常也更受欢迎。

As always, the full code for the examples is available over on GitHub.

与往常一样,这些示例的完整代码可在 GitHub 上获取。