Mocking extension functions


#1

Our team has made the switch to Kotlin and generally all is good. However, we have a persistent issue with mocking when writing tests. Mockito 2 has alleviated this somewhat, but we still have the problem of testing code that calls extension functions.

As extension functions are static, Mockito refuses to deal with them and tools like PowerMock and JMockit provide clumsy solutions (if we can get them working at all).

Extension functions are a big feature of Kotlin and we make heavy use of them in our libraries and it is currently pretty crippling that we cannot test these effectively without having to resort to a higher level of testing or by breaking encapsulation and mocking the code called by the extension function itself.

Therefore the question is, what is the preferred approach to mocking in Kotlin? What are the best frameworks/techniques to use? Is there a Kotlin-specific mocking tool available/in-dev? How do JetBrains test the stdlib (which makes extensive use of extension functions)?


#2

We test the stdlib using the tried and true techiniques of calling the functions, passing the input and verifying the output. We don’t see any situations where mocking would be useful for testing the standard library.

We’re also not working on any mocking tools for Kotlin.


#3

Kotlin is in desperate need of a kotlin native mocking tool with the equivalent functionality of JMockit for java.

Using the “tried and true techniques of calling the functions” is an arrogant answer, frankly. Sometimes that is simply not an option. What if we want to add an extension function to a class that we cannot construct directly, which is commonplace when adding functionality to practically any framework?


#4

It’s true that there are cases when mocking is required. I phrased my answer the way I did because the question seemed to imply that mocking is a required tool for testing any code, and that’s not the case.


#5

Didn’t mean to imply that mocking was required for testing any code and I’d love to keep my code purely functional and be able to test without any mocking. However, in practice, you’re very lucky if you get to work on a project like that. In an enterprise SOA like ours, mocking is always going to be needed.

My principal example, where we keep hitting this issue, is where we have a client library for a service. We generally keep the API for that library very close to the published service API. However, there are often utility functions that we want to make available to all users of the client library and so we implement those with extension functions (in the client library).

In the consumer of the client library, I shouldn’t need to care less whether the function I’m calling is on an interface or is an extension function and generally I don’t. This only becomes an issue when I try to mock the client library and I am only able to mock some of the methods. This situation is exacerbated when the client library and consumer are written by members of different teams whom may not have access to each others’ source code.

I’m happy to elaborate more, but I hope you can appreciate that while we can all agree that mocking is not always needed for testing code, a language will need mocking support in order to be accepted in the modern enterprise, so I’d really appreciate an answer to my original question.


#6

So this is not really about testing the extension functions themselves, but more about making it easy to test the code which uses an API implemented as extension functions. This is definitely a valid use case, and unfortunately I don’t think Kotlin has a good answer to that at this time (that’s why I only replied to the part of your question about testing the standard library).


#7

Sorry, my post was way too harsh.

It would be nice to be able to write 100% new code - to never have to deal with legacy code or work with other people’s libraries and frameworks. But that’s just not the real world.

Even with new code, sometimes you have to deal with a library or framework that imposes undue object construction/usage constraints. Or sometimes you have to integrate with an external production system and do not have access to a non-prod instance. The fact is that mocking has its place, and unfortunately somethings are difficult or even impossible to mock with the current tools.

It’s way too late in the evolution of the language, but I wish the designers had taken advantage of the opportunity they had at the beginning and built in capabilities to make full testing much easier.


#8

What capabilities do you mean? Do you have some feature in mind? Is it somehow breaking so we could not implement it after the language has been released?


#9

Hi mocking library designed for Kotlin is finaly here. Mocking extension functions is supported http://mockk.io/#extension-functions