Learn Kotlin Through Unit Tests

David Herman
Nov 7 · 10 min read

At I/O in 2019, we announced that Android is going Kotlin-first. However, some developers have mentioned they’re still uncertain how to proceed. It’s a scary first step to begin writing Kotlin code, especially if no one on the team is familiar with it.

Those of us on the Android Studio profilers team approached this incrementally. The first step was requiring all our unit tests to be written in Kotlin moving forward. Because these classes were isolated from production code, any initial missteps we made would be contained.

During this time I put together the following guide by collecting common issues that our team observed across several code reviews. I am reproducing it below in hopes that it helps others in the broader Android community.

Note: This post is aimed at Kotlin beginners. If you and your team are already writing Kotlin code effectively, this post may not include much new information for you. However, if you do read it and think you would have included something I didn’t, consider leaving a comment!


IDE Action: Convert Java File to Kotlin File

If you’re using Android Studio, the easiest way to start learning Kotlin is to write your test class in Java and then convert it into Kotlin by selecting Code → Convert Java File to Kotlin File from the menu bar.

This action may ask you “Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?” I recommend selecting “No” so you can focus on just one file at a time.

Although this action generates Kotlin code, what gets produced often leaves room for improvement. The following sections highlight common tips we collected from dozens of code reviews over such auto-generated code. Of course, there is far more to the Kotlin language than what is discussed below, but to keep this guide to the point, it only focuses on the recurring issues we observed.

High Level Language Comparison

Java and Kotlin at a high level look pretty similar. The following is a skeleton test class written in Java and then in Kotlin.

It’s worth noting what’s streamlined in Kotlin:

  • Methods and classes are public by default.
  • The void return type doesn’t need to be explicitly declared.
  • There are no checked exceptions.

Semicolons are optional

This is one of those changes that probably feels really uncomfortable at first. In practice, you don’t need to worry about it too much. Just write your code, and if you put in semicolons out of habit, the code will still compile and the IDE will point them out. Just remove them all before submitting.

Hate this choice or not, Java already removes semicolons in some places, which you can notice if you compare with C++ (which requires semicolons in more places).

Types are declared at the end

Like optional semicolons, this change is one that you’re likely to find very hard to accept if you’re not used to it. It’s the exact opposite order that many have had ingrained into them over their programming career.

However, the advantage with this syntax is it makes it easier to omit types when they can be inferred. This is touched on further in a later section “Omitting variable types”.

This syntax also puts more emphasis on the variable itself and not its type. I find this order actually sounds more natural when talking about the code out loud:

The final thing I’d say about this syntax is, as awkward as it is to use at first, you will get used to it over time.

Constructors without “new”

Kotlin does not require the new keyword before a constructor call.

This may feel at first like you’re losing crucial information, but not really — many functions in Java allocate memory under the hood, and you never cared. Many libraries even have static creation methods, such as the following:

So, really, Kotlin just makes this more consistent. Any function may or may not allocate memory as a side effect.

This also cleans up the pattern where you allocate a temporary class just to call a function on it without assigning it to anything.

Mutability and immutability

Variables in Java are mutable by default and require the final keyword to make them immutable. In contrast, Kotlin does not have the final keyword. Instead, you need to tag properties with val to indicate a value (immutable) or var to indicate a variable (mutable).

Often in Java, you’ll encounter many fields that could have been final but the keyword was omitted (likely by accident as it is easy to forget). In Kotlin, you must be explicit about this decision on every field you declare. If you’re not sure what it should be, just mark it val by default and change it to var later if requirements change.

As an aside, in Java, function parameters are always mutable and, like fields, can be made immutable by using final. In Kotlin, function parameters are always immutable — that is, they are implicitly tagged as val.

Nullability

Kotlin obsoletes the @NotNull and @Nullable annotations. If a value can be null, you need to simply declare its type with a question mark.

In certain situations, if you are sure a nullable value will always be not-null, you can use the !! operator to assert that.

If you apply !! incorrectly, it can cause the code to throw a NullPointerException. Inside a unit test, this just causes a test failure, but you should be extra careful when using this in production code. In fact, many consider !! in production code a potential code smell (although there’s enough nuance here that this point probably requires its own blog post).

In a unit test, it is more acceptable to assert that a specific case is valid using the !! operator, because if this assumption ever stops being true, the test will fail and you can fix it.

If you are sure it makes sense to use the !! operator, then you should apply it as soon as possible. For example, do the following:

But don’t do this:

Omitting variable types

In Java, you will see lots of code like this:

In Kotlin, these type declarations are considered redundant and don’t need to be written twice:

“But wait!” you cry out, “Sometimes I intended to declare those types!” For example:

This can be done in Kotlin using the following syntax:

No checked exceptions

Unlike Java, Kotlin does not require that its methods declare what exceptions they throw. There is no longer a difference between checked exceptions and runtime exceptions.

However, in order to allow Java to be able to call into Kotlin code, Kotlin does support declaring exceptions indirectly, using the @Throws annotation. The Java → Kotlin action plays it safe and always includes this information.

But you never have to worry about your unit tests being called from a Java class. Therefore, you can save some lines and safely remove these noisy exception declarations:

Omitting parentheses with lambda calls

In Kotlin, if you want to assign a closure to a variable, you’ll need to declare its type explicitly:

However, if everything can be inferred, this can be shortened to just

For example,

Note that, in Kotlin, if the last parameter of a function is a lambda call, then you can write the closure outside of the parentheses. The above is identical to:

However, just because you can, doesn’t mean you should. Some might say the fold call above looks weird. Other times this syntax can reduce some visual noise, especially if the only parameter to the method was a closure. Let’s say we want to count even numbers. Compare the following:

with

Or compare:

with

Regardless of what you think is the best approach, you will see this syntax used in Kotlin code, and it can be auto-generated by the Java → Kotlin action, so you should make sure you understand what’s going on when you see it.

equals, ==, and ===

Kotlin diverges from Java around equality testing.

In Java, double-equals (==) is used for instance comparison, which is distinct from the equals method. While this might sound fine in theory, in practice, it is easy for a developer to accidentally use == when they meant to use equals. This could introduce subtle bugs and take hours to spot or debug.

In Kotlin, == is essentially the same thing as equals — the only difference being it also handles the null case correctly. For example, null == x evaluates correctly, while null.equals(x) throws an NPE.

If you need instance comparison in Kotlin, you can use triple-equals (===) instead. This syntax is both more difficult to misuse, and it is easier to spot.

Most of the time you write Kotlin code, you’ll want to use == because the need for === is relatively rare. As a precaution, the Java to Kotlin converter will always convert == to ===. For readability and intention, you should consider restoring back to == when possible. This is common with enum comparisons, for example.

Remove field prefixes

In Java, it is common to have a private field paired with a public getter and setter, and many codebases attach a prefix on the field, a vestige of Hungarian notation.

This prefix is meant to be a useful marker, only visible to the implementation of the class, making it easier to distinguish fields local to the class from, say, parameters passed into a function.

In Kotlin, fields and getters/setters are merged into a single concept.

However, when you auto convert code, the Java prefix sometimes gets carried over, and what was once a detail hidden inside the class can leak into its public interface.

In order to prevent prefixes from leaking, it is recommended to get in the habit of removing them for consistency.

Fields without prefixes may make the occasional code review using web tools a bit harder to read (for example, in a function that’s too long in a class that’s too large). However, when you read the code inside an IDE, it’s clear which values are fields and which are parameters by their syntax highlighting. Removing prefixes may also encourage better coding habits around writing more focused methods and classes.


Closing Thoughts

Hopefully, this guide helps kickstart your Kotlin learning. First, you’ll start by writing Java and converting it to Kotlin, then you’ll write Java-like Kotlin, and finally, before too long, you’ll be writing idiomatic Kotlin code like a pro!

This post just scratches the surface of what you can do with Kotlin. It aims to be a minimal set of notes for those who don’t have a lot of time and just need to get their first Kotlin test up and running quickly, while still introducing them to a fair amount of the language’s foundation.

However, it likely won’t cover everything you will need. For that, consider the official documentation:

Language Reference: https://kotlinlang.org/docs/reference/
Interactive Tutorials:
https://try.kotlinlang.org/

The language reference is very useful. It covers all topics in Kotlin without going so deep as to be overwhelming.

The tutorials will give you an opportunity to practice using the language, and they also include koans (a series of short exercises) to help confirm your newly acquired knowledge.

And finally, check out our official codelab for refactoring to Kotlin. It covers topics introduced in this blog post and much, much more.

Android Developers

The official Android Developers publication on Medium

David Herman

Written by

I am a team lead on the Android Studio team (at Google). I’ve worked on profilers and improving data binding integration.

Android Developers

The official Android Developers publication on Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade