1. Overview

In this tutorial, we’ll discuss a very important topic in unit testing: mocking and verifying lambda expressions in Kotlin.

2. What Is Mocking?

To mock in Kotlin refers to a technique for creating fake implementations of certain components or dependencies with which a unit of our code interacts.

The fake implementations that we create, also called mocks, simulate the behavior of our real components without executing their full functionality.

This is a good practice to adopt, particularly when we want to isolate the unit of code we’re testing from the external dependencies.

3. What Is a Lambda Expression?

A lambda expression defines a small piece of code that we can pass around and use as an argument to other functions or methods. Lambda functions are helpful when we want to test our units since they allow us to define custom behavior for our mock objects.

Here’s a simple example of a lambda expression:

val add: (Int, Int) -> Int = { a, b -> a + b }

In our example above, add is simply a variable that holds a lambda expression, which defines a function that takes two integer parameters and returns their sum.

4. Using Mockito to Mock and Verify Lambdas

We’ll use the Mockito library in this case to verify the behavior of our operation.

We’ll use this class for verification:

class Calculator(private val operation: (Int, Int) -> Int) {
    fun calculate(a: Int, b: Int): Int {
        return operation(a, b)
    }
}

Our first step is to add the Mockito dependency to the build.gradle file of our project:

dependencies {
    testImplementation("org.mockito:mockito-core:VERSION")
}

This is how we write our tests using the Mockito framework to mock and verify our lambda:

@Test
fun testLambda_WithMockito() {
    val operationMock: (Int, Int) -> Int = mock()
    val calculator = Calculator(operationMock)
    whenever(operationMock.invoke(any(), any())).thenReturn(50)
    val result = calculator.calculate(10, 5)
    assertEquals(50, result)
    verify(operationMock).invoke(eq(10), eq(5))
}

In our code above, in our testCalculateWithMockito() function, we create a mock of the (Int, Int) -> Int functional interface using mock().

We then create an instance of our Calculator class by passing the mocked operationMock as an argument.

Afterward, we use whenever() to specify the behavior of operationMock when invoked with any two integer arguments. In our case, we’ll instruct Mockito to return 50 whenever the lambda expression is called.

Finally, we call the calculate() method on our calculator instance by providing the arguments as 10 and 5, and this should assert to 50 always.

Notably, our lambda expression is being mocked to always return 50 when invoked with any arguments. This means that regardless of the input values, such as 10 and 5, the lambda always returns 50.

5. Using the Mockk Library

We can also use the Mockk library to mock and verify lambda expressions in Kotlin. Mockk is also a mocking library designed specifically for Kotlin. It provides a clean and expressive way to mock and verify functions and lambdas.

To use Mockk to verify and verify our lambda, we’ll first add the Mockk dependency to our build.gradle file:

dependencies {
    testImplementation("io.mockk:mockk:1.12.0")
}

After adding the dependency, we’ll write our test to mock and verify our lambda expression of the same Calculator class:

@Test 
fun testLambda_UsingMockk() { 
    val operationMock = mockk<(Int, Int) -> Int>()
    every { operationMock(any(), any()) } returns 50
    val calculator = Calculator(operationMock)
    val result = calculator.calculate(10, 5) 
    assertEquals(50, result) 
    verify { operationMock(10, 5) }
}

In this example, we mocked the operationMock expression and then specified our behavior using every and returns. We then created an instance of our Calculator class with our mocked lambda and tested its behavior.

The verify function from Mockk is used to verify that our lambda is called with our expected arguments.

6. Using Kotlin’s Built-in Functionality

While using this method, we usually have the capability to control the behavior of our lambda and verify various interactions.

To see the process of verifying lambda expressions in Kotlin, let’s use the following code snippet:

@Test
fun verifyLambdasCorrectly() {
    val operation: (Int, Int) -> Int = { a, b -> a - b } 
    val calculator = Calculator(operation) 
    val result = calculator.calculate(10, 5) 
    assertEquals(5, result) 
}

In this snippet, a subtraction operation takes place, unlike the first two examples we saw using the Mockk and Mockito libraries. Our 0peration lambda subtracts the second parameter b from the first parameter a. Our test verifies this using the method with arguments 10 and 5, which results in a value of 5.

7. Conclusion

In this article, we learned various methods to mock and verify lambda expressions in Kotlin.

This included using external libraries such as Mockk and Mockito. Our last method was using Kotlin’s built-in functionality.

As always, the full implementation of these examples is available on GitHub.