Unit Testing in Kotlin

Post on 14-Apr-2017

81 views 2 download

Transcript of Unit Testing in Kotlin

Unit Testing in Kotlin

Egor AndreeviciSoftware Developer @ 1&1@EgorAnd

Android: In The Java Zone

Java Kotlin

+ Official+ Stable- Old- Verbose

+ Modern+ Expressive- Stable?- Support?

Starting with Kotlin on Android?

Start small!

Start with unit tests!

Unit Tests Are Good

Benefits of Unit Tests

Provide a safety net around your code

Document your code… what?

Promote good design practices

Bad Documentation

/*** Get a subview of the root view at a certain position.** @param position Position, 0 <= position < root child count* @return Subview at given position, or {@code null} if position is out of * bounds*/public View getViewAtPosition(int position) { if (position >= 0 && position < root.getChildCount()) { return root.getChildAt(position); } return null;}

Bad Documentation

/*** Get a subview of the root view at a certain position.** @param position Position, 0 <= position < root child count* @return Subview at given position, or {@code null} if position is out of* bounds*/public View getViewAtPosition(int position) { if (position >= 0 && position < root.getChildCount()) { return root.getChildAt(position); } throw new IndexOutOfBoundsException("Invalid position " + position);}

A Better Test

@Test public void shouldReturnNullIfCalledWithInvalidPosition() { doReturn(0).when(mockParent).getChildCount();

assertThat(docs.getViewAtPosition(0)).isNull();}

EvenBetterTest.kt

Kotlinize

@Test fun shouldReturnNullIfCalledWithInvalidPosition() { doReturn(0).`when`<ViewGroup>(mockParent).childCount

assertThat(docs.getViewAtPosition(0)).isNull()}

Better Method Names

@Test fun `Should return null if called with invalid position`() { doReturn(0).`when`<ViewGroup>(mockParent).childCount

assertThat(docs.getViewAtPosition(0)).isNull()}

Better Mocking with Mockito-Kotlin

● Reified types for mock creation

● Fluent method mocking syntax

● More niceties

Better Mocking with Mockito-Kotlin

private var mockParent = mock<ViewGroup>()

Better Mocking with Mockito-Kotlin

// private var mockParent = mock<ViewGroup>()

private var mockParent: ViewGroup = mock { on { childCount } doReturn 0}

Better Mocking with Mockito-Kotlin

@Test fun `Should return null if called with invalid position`() { whenever(mockParent.childCount) doReturn 0

assertThat(docs.getViewAtPosition(0)).isNull()}

How Does It Work?

inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)

Better Assertions with Kluent

@Test fun `Should return null if called with invalid position`() { whenever(mockParent.childCount) doReturn 0

docs.getViewAtPosition(0) `should be` null}

How Does It Work?

import org.junit.Assert.*

infix fun Any?.`should be`(theOther: Any?) = assertSame(theOther, this)infix fun Any?.shouldBe(theOther: Any?) = this `should be` theOther

Other Goodies

Multiline Strings

val json = """ { "name": "Bob", "age": 57 } """

@Test fun `Should parse JSON correctly`() { gson.fromJson(json, Person::class.java) `should equal` Person("Bob", 57)}

“with” for Multiple Assertions

@Test fun `Should parse JSON correctly #2`() { val person = gson.fromJson(json, Person::class.java)

with(person) { name `should equal` "Bob" age `should equal` 57 }}

Factory Functions with Named Args

public class Person {

private String name; private int age; private boolean isAKotlinProgrammer;

public Person(String name, int age, boolean isAKotlinProgrammer) { this.name = name; this.age = age; this.isAKotlinProgrammer = isAKotlinProgrammer; }

…}

Factory Functions with Named Args

fun person( name: String = "", age: Int = 0, isAKotlinProgrammer: Boolean = false) =

Person(name, age, isAKotlinProgrammer)

@Test fun `Should ...`() { val person = person(name = "Bob", age = 57)

...}

@JvmOverloads

@JvmOverloadsfun person( name: String = "", age: Int = 0, isAKotlinProgrammer: Boolean = false) =

Person(name, age, isAKotlinProgrammer)

...and more magic in store!

Thanks!

Egor AndreeviciSoftware Developer @ 1&1@EgorAnd