1. Overview

Kotlin has great compatibility with Java, but one difference is that Kotlin doesn’t contain the static modifier, and when it comes to mocking, Java static methods aren’t convenient to access. The mocking library Mockk has a feature that allows us to mock static Java methods easily.

In this tutorial, we’ll learn how to use this function and undo its effects after we’re done with it.

2. Using Mockk on a Java static Method

To set up our demonstration, let’s use RandomNumberGenerator as an example of a static Java class. We assume that this is whatever static method our external implementation gives us:

public class RandomNumberGenerator {
    public static Double random() {
        return Math.random();
    }
}

Let’s use it in a simple example to determine the result of a coin flip based on the class we have created:

fun coinFlip() = if(RandomNumberGenerator.random() < 0.5) "heads" else "tails"

Some unit tests won’t require any change or mocking to work. Validating that our coin flip never throws an exception is an example of that:

@Test
fun `Doing a coin flip should not throw an exception`() {
    repeat(1000) {
        coinFlip()
    }
}

In some other cases, however, we might want to assert the mechanisms behind our flip, which is the static random() method. For example, we may need to validate specific rules based on the result of the method call.

In our sample function, the assertion we want depends on an assumption: Whenever the static method is called, we’ll replace it with a class that returns what we want. The test should have a format similar to:

@Test
fun `Heads should be returned whenever RandomNumberGenerator returns less than 0,5`() {
    // Simulate RandomNumberGenerator.random() returning a number < 0.5
    assertEquals(coinFlip(), "heads")
}

To make sure we can control the returned value, let’s use mockkStatic() to fine-tune the result:

@Test
fun `Heads should be returned whenever random returns less than 0,5`() {
    // Simulate RandomNumberGenerator.random() returning a number < 0.5
    mockkStatic(RandomNumberGenerator::class)
    every { RandomNumberGenerator.random() } returns 0.1
    assertEquals(coinFlip(), "heads")
}

3. Removing a Mockk After Using It

We need to ensure that we don’t mess with the static namespace that we used, as many other methods might use the same static method. In other words, we don’t want our mocked behavior to leak into other tests. So, let’s unmock the static class we mocked previously:

@AfterEach
fun `Remove RandomNumberGenerator mockks`() {
    unmockkStatic(RandomNumberGenerator::class)
}

4. Removing All Mockks at Once After Tests

We can also unmock what we’ve mocked after any test finishes running by using unmockkAll(). That limits the unmockk calls to a single place and ensures we won’t leak any modification to the rest of our test suite.

To do that, let’s add a method to our unit test class and annotate it with @AfterEach:

@AfterEach
fun `Remove all mocks`() {
    unmockkAll()
}

5. Conclusion

In this tutorial, we’ve learned how to use Mockk’s mockkStatic to mock static Java methods. We also prepared our test suite to unmockk any mocks we might have set up, ensuring we don’t pollute the context for other tests.

As always, the implementation used in this article can be found over on GitHub.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.