Welcome in the last week of Advent of Kotlin. Many great challenges behind, and the last and the most challenging and mind-opening task ahead. This time we will feel a bit like developers of mocking libraries.

We use mocking libraries like Mockito or MockK every day. We trust them, and we expect them always to work correctly. We often treat mocking as must-have for development, and we often forget how hard it is to implement a mocking library. To be honest, since I started digging deeper into these libraries, I have a sense that it is a miracle that they exist and that they work so well. Great that there were people who spend so much time and made this possible. Partially as a tribute, and partially because it is good to have some sense of how work everything you use, this week we are going to implement a very simple interface mocking for JVM.

To make it clear: Class mocking is more complicated and normally done using some additional library like ByteBuddy. Though an interface mocking is way easier thanks to Java support. The object we will use is the Proxy.

Interface mocking

What we want to implement is a way to create an object, mock, that behaves like an interface, but instead of implementing one, it acts based on some specification. For instance, in the MockK we can specify it in the following way:

As you can see, in every we specify what should be returned when we ask for the method. We don’t implement a library, and we don’t need DSL so we can just replace it with a bit simpler API:

Here we can see method setReturnValue that only says what should be returned and method setBody that can be used to specify the whole body of this function. We should also be able to use arguments.

Interface proxy

This task is relatively simple thanks to the fact that Java has a built-in support for proxying interfaces. What is an interface proxy? It is an object that pretends to be an interface, and instead of implementing methods, it directs all calls to the same function. Let’s see an example:

A great example of how this proxy can be used is Retrofit. In this library, we define network calls in interfaces using methods and annotations:

Using these definitions, we can create instances and use them to do internet calls:

create method, as you can guess, returns a proxy. Here you can see it in the code. Each usage is passed to the same handler and then depending on annotations used in the interface, the network call is constructed.

The same way we can implement interface mocking. For each instance, we can just hold information about how each call should be served and use it when this method is used. The big question is how can we pass this information? The answer is that you need to allow a special recording mode.

Recording mode

The biggest problem is how to pass a piece of information what should be returned or invoked. We cannot pass it directly to the object because it is already mocked and it does not have any methods expect of those on the interface. We need to pass this information while calling those methods:

How? The simplest answer is to switch some recording mode for this time. Not pretty nor thread-safe, but if we assume that only one test will run at the same time and that these are tests and not production code, it is fine.

Then in our proxy, we will say:

If you have some better idea, do it. Remember that the first priority here is to make it work. It is a hard and very unusual problem, and it requires some hacking. Java was not build to support mocking.

Task

Implement simple interface mocking to make this work:

If you are more ambitious, you can push it forward and also allow some arguments. We can preassume that they are passed to the function as a list of Any :

Test on different interfaces with single and multiple methods. What should happen when a body is set twice to the same method?

Apply challenge

At the end of this week, we will share solution we liked the most. If you want us to consider your solution, you need to share a link to code (can be GitHub snippet or a link to Kotlin REPL) on Twitter, with #AdventOfKotlin18 tag. Alternatively, you can send an email with your solution to contact@kt.academy email. The final deadline is on 23 Dec at 12 pm (CET). More details here, Good luck :)

Results

This task was thought, and yet there were heroes who solved it. I would like to congratulate each of them. I received good answers from:

Jose Ignacio Acin Pozo (SO, GitHub)

Christian Fuchs

Balázs Németh

Péter Gulyás

Oliver Perez

The basic mocking functionality was correctly implemented by each of them. This functionality can be shown using this minimalistic implementation:

Then one can add some DSL like in the implementation by Oliver Perez:

Check it out on his repository.

The hardest part of this challenge was using any() instead of an argument. On the end, we need to use this function so something needs to be passed. What should it be?

The simplest idea was to let a user decide what should it be:

This solution has been sent by Christian Fuchs, and I must say that I was impressed by the simplicity of this trick. The whole implementation is on Github:

The implementation that I enjoyed the most was sent by Jose Ignacio Acin Pozo (SO, GitHub). This is our winner for this week. Surprisingly it was the first send implementation. The whole code is well organized and functional, and this is how he solved the problem of getting any value:

In other words: if it is a primitive or a known type, use an instance from a special map. Otherwise, create an instance using a constructor without any arguments. Also, cache values to not create new instances for already created types. This is close to perfect. It might be moved a step forward by checking if this constructor exists and if it does not, checking a constructor with one more argument. Then filling these arguments by creating random values in the same way. Not perfect, but good enough. As you can see, writing mocking libraries is definitely not easy.

This solution, together with all previous solutions, can be found on GitHub:

Good job!