NPE when mocking value class
  • 24-Apr-2023
Lightrun Team
Author Lightrun Team
Share
NPE when mocking value class

NullPointerException when mocking value class with any() matcher

Lightrun Team
Lightrun Team
24-Apr-2023

Explanation of the problem

The issue is that attempting to mock a value class in the code results in a failure. Removing the value modifier resolves the issue. A request for support of value classes has been made, and in the meantime, a workaround is sought.

The code relies on the following dependencies:

plugins {
kotlin("jvm") version "1.5.31"
java
}

dependencies {
implementation(kotlin("stdlib"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
testImplementation("org.mockito.kotlin:mockito-kotlin:3.2.0")
testImplementation("org.mockito:mockito-inline:3.12.4")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

It includes an interface, MyRepository, which contains a function findByEmail, taking an argument of the value class Email, and returning an instance of the Entity data class.

The Email class is a value class with a single field email. It is marked with the @JvmInline annotation, and includes a companion object of that returns a new instance of the class with a lower-cased email field.

The Entity class is a data class with a single field name.

There is a test class MyRepositoryTest with a single test function thisTestThrowsNpe, which is expected to fail due to an issue with mocking the MyRepository class using mockito-kotlin. The test function creates a mock instance of the MyRepository interface, and sets up a mock behavior to return an instance of Entity with the name field set to “name”.

The stack trace of the exception thrown on running the test function contains a NullPointerException in MyRepositoryTest.kt on line 20, inside a lambda function passed to given method of mockito-kotlin.

Troubleshooting with the Lightrun Developer Observability Platform

 

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for NullPointerException when mocking value class with any() matcher

Value classes were introduced in Kotlin 1.1 as a way to define lightweight, inline classes that can help improve performance and type safety. However, not all testing frameworks and libraries fully support value classes yet, which can cause issues when trying to write tests that involve value classes. In particular, Mockito, a popular Java mocking framework used in Kotlin, does not provide built-in support for value classes, which can result in NullPointerExceptions or other errors when trying to stub or mock methods that use value classes as parameters.

One workaround for this issue is to use a custom function that explicitly checks for value classes and provides a way to compare them using their underlying data types. The eqValueClass function provided in one of the answers is an example of such a function. It takes the expected value and a function that extracts the underlying data type from the value class, and then uses a supplied test function to compare the actual value with the expected value. This workaround can help prevent NullPointerExceptions and other issues when using value classes with Mockito, but it requires additional setup and may be less convenient than built-in support.

It’s worth noting that the lack of built-in support for value classes in Mockito is not unique to Kotlin; many other languages and frameworks also struggle with supporting value classes and other new language features. As such, it’s important for developers to stay informed about the current state of support for different language features and libraries, and to test their code thoroughly to ensure that it works as expected. With time, it is likely that more testing frameworks and libraries will add support for value classes and other new language features, but until then, workarounds like the one described above may be necessary.

Other popular problems with NullPointerException when mocking value class with any() matcher

 

Problem: “NullPointerException thrown when stubbing” error

This error is typically caused when attempting to mock a method that returns a value class or data class. Because these types are generated at runtime, Mockito-Kotlin is unable to create a mock instance of them, resulting in the NullPointerException error.

Solution:

To overcome this issue, users can employ a workaround such as the eqValueClass function or create custom matchers that explicitly specify the type of the value class. Additionally, using the eq function with explicit type parameters can also help avoid this issue.

Problem: Difficulty in stubbing generic methods

This issue can arise because Mockito-Kotlin does not always handle generic types correctly. As a result, users may find that they are unable to properly stub these methods, resulting in errors or unexpected behavior.

Solution:

One solution to this problem is to use the onGeneric function instead of the on function when stubbing a generic method. This will ensure that Mockito-Kotlin properly handles the generic type and stubs the method as expected. Additionally, users can try using the doAnswer or doReturn functions instead of the on function to stub the method.

Problem: Difficulty in verifying the invocation of a method with a parameter of a value class

Similar to the problem with stubbing, Mockito-Kotlin may be unable to properly handle value classes at runtime, resulting in errors or unexpected behavior when attempting to verify the invocation of a method.

Solution:

One workaround for this issue is to use the argument capture feature of Mockito-Kotlin. By using this feature, users can capture the value of the parameter passed to the method and then compare it to the expected value using the eqValueClass function or a custom matcher. Another solution is to use a plain object instead of a value class as the parameter for the method, although this may not be feasible in all cases.

A brief introduction of Mockito-Kotlin

Mockito-Kotlin is a library that provides Kotlin-friendly extensions to the popular mocking framework Mockito. It allows developers to write more concise and expressive test code by leveraging Kotlin’s features such as named parameters, default arguments, and extension functions. Mockito-Kotlin aims to provide a seamless integration with Mockito, so users can continue to use their existing Mockito knowledge and practices while taking advantage of Kotlin’s features. The library is actively maintained and has a growing user base in the Kotlin community.

One of the main benefits of using Mockito-Kotlin is the ability to write more readable and maintainable test code. With the help of Kotlin’s syntax, test code can be written in a more concise and expressive way, reducing boilerplate and making it easier to understand the intent of the test. Mockito-Kotlin also provides a number of useful extensions to Mockito, such as whenever and doAnswer, which make it easier to work with Kotlin types such as lambdas and nullable types. Additionally, the library integrates seamlessly with other testing frameworks such as JUnit and Spek, making it a versatile choice for testing Kotlin code.

Overall, Mockito-Kotlin is a valuable tool for any Kotlin developer looking to write high-quality test code. Its Kotlin-friendly syntax and integration with Mockito make it easy to use and understand, while its extensions and integrations with other testing frameworks make it a powerful tool for testing Kotlin code. As Kotlin continues to gain popularity as a programming language, Mockito-Kotlin is likely to become an even more important tool for developers looking to write robust and maintainable test code.

Most popular use cases for Mockito-Kotlin

  1. Writing unit tests: Mockito-Kotlin is a mocking framework for Kotlin that allows developers to create mock objects of classes and interfaces. This makes it useful for writing unit tests for Kotlin code, especially when testing interactions between different components of the system. For example, here’s how to create a mock object of a class using Mockito-Kotlin:
val mockedList = mock<List<String>>()
  1. Verifying method calls: Mockito-Kotlin provides a set of methods that can be used to verify that specific methods on a mock object were called during a test. This is useful for ensuring that the code under test is interacting with its dependencies correctly. Here’s an example of how to verify that a method was called:
verify(mockedList).add("item")
  1. Stubbing method calls: Mockito-Kotlin also allows developers to stub method calls on mock objects, which can be useful for testing error conditions or different paths through the code. Here’s an example of how to stub a method call:
whenever(mockedList.get(0)).thenThrow(RuntimeException("error"))

Overall, Mockito-Kotlin is a powerful tool for testing Kotlin code and can save developers a lot of time and effort when writing unit tests.

Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.