Photo by Jakob Owens

Sealed Classes Unit Tests💥

Fernando Prieto
2 min readJul 1, 2020

Some months ago, I was working in an Android project where I decided to create a view template that based on the sealed class received on the view, I was able to show different layout structures: one of those possible view structures would have a title, subtitle and image. Another one, those three elements plus an extra text field and so forth.

At some point, I felt the need of testing the type of sealed class that the View Model was able to notify the observer (View) through LiveData. And I found an interesting post by Danny Preussler, where he explained a great approach using some factories, annotations and generics (Parameterized tests with Kotlin’s Sealed Classes).

In his project, he was able to test many different sealed classes : simple, nested and custom. But I decided to focus on the custom one, which is the most common type that I usually work with: different data classes within the sealed class, each one, with different parameters.

I used some common parameters in all of the sealed sub-classes. To achieve that, I defined an interface that had got all of those parameters:

And the sealed class I defined, as example, implementing that interface is:

As you can see, it contains a class ErrorCode , annotated with @InstagramErrorCode, which I will explain later:

Test goals 🎯

The first thing I wanted to test was, the expected sealed sub-class, using Parameterized Test . So I could pass as arguments the different cases with the expected KClass.

And the second thing, I wanted to achieve in my test was the different constructors availability check. That confirms the number of data classes defined within the sealed class .

Parameterized Test by Type 🔬

Test by Class 📦

WHY another custom Factory ⁉️

In order to use the class developed by Danny Preussler SealedClassesArgumentsProvider , we need to identify and return a type value from the KClassifier represented by every parameter.

As I decided to add a List and an Enum Class , I must specify the returned value. And in the case of the Enum Class , I thought that an interesting way to do it, was finding the annotation specified for that class, then returning a default Enum Type asErrorCode.TimeOut

WHY another annotation ⁉️

When I was specifying the return type from the KClassifier I found there was a better solution than the first approach (hardcoded value) I made.
Let’s compare this initial solution (NOT GOOD):

else -> if ((type.classifier as KClass<out Any>).qualifiedName == “sctestingplayground.ErrorCode”) ErrorCode.TimeOut else null

And let’s check now, the improvement using the findAnnotation inline function:

else -> if ((type.classifier as KClass<out Any>).findAnnotation<InstagramErrorCode>() != null) ErrorCode.TimeOut else null

Code

You can find the entire example in my Github Kotlin repository:

SealedClassesTestingPlayground

--

--