Skip to content

Commit

Permalink
Merge pull request #135 from nhaarman/handle-null-in-argumentmatcher
Browse files Browse the repository at this point in the history
Handle `null` in argument matchers.
  • Loading branch information
nhaarman committed Dec 10, 2016
2 parents 543238f + b77d969 commit 263344f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,39 @@ inline fun <reified T : Any> anyVararg(): T = Mockito.any<T>() ?: createInstance
/** Matches any array of type T. */
inline fun <reified T : Any?> anyArray(): Array<T> = Mockito.any(Array<T>::class.java) ?: arrayOf()

inline fun <reified T : Any> argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat<T> { it -> (it as T).predicate() } ?: createInstance(T::class)
/**
* Creates a custom argument matcher.
* `null` values will never evaluate to `true`.
*
* @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate.
*/
inline fun <reified T : Any> argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat<T?> { arg -> arg?.predicate() ?: false } ?: createInstance(T::class)

/**
* Creates a custom argument matcher.
* `null` values will never evaluate to `true`.
*
* @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate.
*/
inline fun <reified T : Any> argForWhich(noinline predicate: T.() -> Boolean) = argThat(predicate)
inline fun <reified T : Any> check(noinline predicate: (T) -> Unit) = Mockito.argThat<T> { it -> predicate(it); true } ?: createInstance(T::class)

/**
* For usage with verification only.
*
* For example:
* verify(myObject).doSomething(check { assertThat(it, is("Test")) })
*
* @param predicate A function that performs actions to verify an argument [T].
*/
inline fun <reified T : Any> check(noinline predicate: (T) -> Unit) = Mockito.argThat<T?> { arg ->
if (arg == null) error("""The argument passed to the predicate was null.
If you are trying to verify an argument to be null, use `isNull()`.
If you are using `check` as part of a stubbing, use `argThat` or `argForWhich` instead.
""".trimIndent())
predicate(arg)
true
} ?: createInstance(T::class)

fun atLeast(numInvocations: Int): VerificationMode = Mockito.atLeast(numInvocations)!!
fun atLeastOnce(): VerificationMode = Mockito.atLeastOnce()!!
Expand Down
5 changes: 4 additions & 1 deletion mockito-kotlin/src/test/kotlin/test/Classes.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package test/*
package test

/*
* The MIT License
*
* Copyright (c) 2016 Niek Haarman
Expand Down Expand Up @@ -55,6 +57,7 @@ interface Methods {
fun nullableString(s: String?)

fun stringResult(): String
fun stringResult(s: String): String
fun nullableStringResult(): String?
fun builderMethod(): Methods
}
Expand Down
36 changes: 36 additions & 0 deletions mockito-kotlin/src/test/kotlin/test/MockitoTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ class MockitoTest : TestBase() {
}
}

@Test
fun checkWithNullArgument_throwsError() {
mock<Methods>().apply {
nullableString(null)

expectErrorWithMessage("null").on {
verify(this).nullableString(check {})
}
}
}

@Test
fun atLeastXInvocations() {
mock<Methods>().apply {
Expand Down Expand Up @@ -458,6 +469,30 @@ class MockitoTest : TestBase() {
}
}

@Test
fun stubbingTwiceWithArgumentMatchers() {
/* When */
val mock = mock<Methods> {
on { stringResult(argThat { this == "A" }) } doReturn "A"
on { stringResult(argThat { this == "B" }) } doReturn "B"
}

/* Then */
expect(mock.stringResult("A")).toBe("A")
expect(mock.stringResult("B")).toBe("B")
}

@Test
fun stubbingTwiceWithCheckArgumentMatchers_throwsException() {
/* Expect */
expectErrorWithMessage("null").on {
mock<Methods> {
on { stringResult(check { }) } doReturn "A"
on { stringResult(check { }) } doReturn "B"
}
}
}

@Test
fun doReturn_withSingleItemList() {
/* Given */
Expand Down Expand Up @@ -500,6 +535,7 @@ class MockitoTest : TestBase() {
verify(this).string(isA<String>())
}
}

@Test
fun isA_withNullableString() {
mock<Methods>().apply {
Expand Down

0 comments on commit 263344f

Please sign in to comment.