Upload
egor-andreevici
View
90
Download
2
Embed Size (px)
Citation preview
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