Skip to content

Commit

Permalink
Merge pull request #91 from nhaarman/improve-captors
Browse files Browse the repository at this point in the history
Improve argument captors
  • Loading branch information
nhaarman authored Oct 13, 2016
2 parents fd98501 + 80dbefd commit cd16b04
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,32 @@
package com.nhaarman.mockito_kotlin

import org.mockito.ArgumentCaptor
import kotlin.reflect.KClass

inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T> = KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)

inline fun <reified T : Any> argumentCaptor() = ArgumentCaptor.forClass(T::class.java)
inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T = captor.capture() ?: createInstance<T>()

@Deprecated("Use captor.capture() instead.", ReplaceWith("captor.capture()"))
inline fun <reified T : Any> capture(captor: KArgumentCaptor<T>): T = captor.capture()

class KArgumentCaptor<out T : Any>(private val captor: ArgumentCaptor<T>, private val tClass: KClass<T>) {

val value: T
get() = captor.value

val allValues: List<T>
get() = captor.allValues

fun capture(): T = captor.capture() ?: createInstance(tClass)
}

/**
* This method is deprecated because its behavior differs from the Java behavior.
* Instead, use [argumentCaptor] in the traditional way, or use one of
* [argThat], [argForWhich] or [check].
*/
@Deprecated("Use argumentCaptor() or argThat() instead.")
inline fun <reified T : Any> capture(noinline consumer: (T) -> Unit): T {
var times = 0
return argThat { if (++times == 1) consumer.invoke(this); true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ inline fun <reified T : Any?> anyArray(): Array<T> = Mockito.any(Array<T>::class

inline fun <reified T : Any> argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat<T> { it -> (it as T).predicate() } ?: createInstance(T::class)
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)

fun atLeast(numInvocations: Int): VerificationMode = Mockito.atLeast(numInvocations)!!
fun atLeastOnce(): VerificationMode = Mockito.atLeastOnce()!!
Expand Down
26 changes: 17 additions & 9 deletions mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
import com.nhaarman.expect.expect
import com.nhaarman.mockito_kotlin.argumentCaptor
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.times
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.expect.expect
import com.nhaarman.mockito_kotlin.capture
import org.junit.Test
import java.util.*

class ArgumentCaptorTest {

@Test
fun explicitCaptor() {
/* Given */
val date: Date = mock()
val time = argumentCaptor<Long>()

/* When */
date.time = 5L

verify(date).time = capture(time)
expect(time.value).toBe(5L)
/* Then */
val captor = argumentCaptor<Long>()
verify(date).time = captor.capture()
expect(captor.value).toBe(5L)
}

@Test
fun implicitCaptor() {
fun argumentCaptor_multipleValues() {
/* Given */
val date: Date = mock()

/* When */
date.time = 5L
date.time = 7L

verify(date).time = capture {
expect(it).toBe(5L)
}
/* Then */
val captor = argumentCaptor<Long>()
verify(date, times(2)).time = captor.capture()
expect(captor.allValues).toBe(listOf(5, 7))
}
}
10 changes: 10 additions & 0 deletions mockito-kotlin/src/test/kotlin/MockitoTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ class MockitoTest {
}
}

@Test
fun listArgCheck() {
mock<Methods>().apply {
closedList(listOf(Closed(), Closed()))
verify(this).closedList(check {
expect(it.size).toBe(2)
})
}
}

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

0 comments on commit cd16b04

Please sign in to comment.