CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-nhaarman-mockitokotlin2--mockito-kotlin

Helper functions to work with Mockito in Kotlin

Pending
Overview
Eval results
Files

argument-capturing.mddocs/

Argument Capturing

Type-safe argument capturing with Kotlin-friendly APIs and support for multiple argument capture patterns. Essential for capturing and inspecting arguments passed to mock methods.

Capabilities

Basic Argument Captors

Functions for creating argument captors for different numbers of types.

/**
 * Creates a KArgumentCaptor for the specified reified type
 * @returns KArgumentCaptor instance for capturing arguments of type T
 */
inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T>

/**
 * Creates 2 KArgumentCaptors for given types
 * @param a KClass for first type (defaults to reified A::class)
 * @param b KClass for second type (defaults to reified B::class)
 * @returns Pair of KArgumentCaptors for types A and B
 */
inline fun <reified A : Any, reified B : Any> argumentCaptor(
    a: KClass<A> = A::class,
    b: KClass<B> = B::class
): Pair<KArgumentCaptor<A>, KArgumentCaptor<B>>

/**
 * Creates 3 KArgumentCaptors for given types
 * @param a KClass for first type (defaults to reified A::class)
 * @param b KClass for second type (defaults to reified B::class)
 * @param c KClass for third type (defaults to reified C::class)
 * @returns Triple of KArgumentCaptors for types A, B, and C
 */
inline fun <reified A : Any, reified B : Any, reified C : Any> argumentCaptor(
    a: KClass<A> = A::class,
    b: KClass<B> = B::class,
    c: KClass<C> = C::class
): Triple<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>>

Usage Examples:

import com.nhaarman.mockitokotlin2.*

// Single argument captor
val userCaptor = argumentCaptor<User>()
verify(userService).saveUser(userCaptor.capture())
val capturedUser = userCaptor.firstValue

// Multiple argument captors
val (userCaptor, emailCaptor) = argumentCaptor<User, String>()
verify(emailService).sendEmail(userCaptor.capture(), emailCaptor.capture())
val capturedUser = userCaptor.firstValue
val capturedEmail = emailCaptor.firstValue

// Three argument captors
val (userCaptor, emailCaptor, templateCaptor) = argumentCaptor<User, String, EmailTemplate>()
verify(emailService).sendTemplatedEmail(
    userCaptor.capture(), 
    emailCaptor.capture(), 
    templateCaptor.capture()
)

Extended Argument Captors

Argument captors for larger numbers of parameters using holder classes.

/**
 * Creates 4 KArgumentCaptors for given types
 * @param a KClass for first type (defaults to reified A::class)
 * @param b KClass for second type (defaults to reified B::class)
 * @param c KClass for third type (defaults to reified C::class)
 * @param d KClass for fourth type (defaults to reified D::class)
 * @returns ArgumentCaptorHolder4 containing 4 KArgumentCaptors
 */
inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any> argumentCaptor(
    a: KClass<A> = A::class,
    b: KClass<B> = B::class,
    c: KClass<C> = C::class,
    d: KClass<D> = D::class
): ArgumentCaptorHolder4<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>>

/**
 * Creates 5 KArgumentCaptors for given types
 * @param a KClass for first type (defaults to reified A::class)
 * @param b KClass for second type (defaults to reified B::class)
 * @param c KClass for third type (defaults to reified C::class)
 * @param d KClass for fourth type (defaults to reified D::class)
 * @param e KClass for fifth type (defaults to reified E::class)
 * @returns ArgumentCaptorHolder5 containing 5 KArgumentCaptors
 */
inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any, reified E : Any> argumentCaptor(
    a: KClass<A> = A::class,
    b: KClass<B> = B::class,
    c: KClass<C> = C::class,
    d: KClass<D> = D::class,
    e: KClass<E> = E::class
): ArgumentCaptorHolder5<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>, KArgumentCaptor<E>>

Usage Examples:

import com.nhaarman.mockitokotlin2.*

// Four argument captors
val captors = argumentCaptor<String, Int, Boolean, Double>()
verify(complexService).processData(
    captors.first.capture(),
    captors.second.capture(), 
    captors.third.capture(),
    captors.fourth.capture()
)

// Five argument captors with destructuring
val (nameCaptor, ageCaptor, activeCaptor, salaryCaptor, dateCaptor) = 
    argumentCaptor<String, Int, Boolean, Double, LocalDate>()

Lambda-Based Argument Captors

Argument captors with immediate lambda evaluation for verification.

/**
 * Creates a KArgumentCaptor with immediate lambda evaluation for fast verification
 * @param f Lambda function applied to the created captor
 * @returns KArgumentCaptor instance after applying the lambda
 */
inline fun <reified T : Any> argumentCaptor(f: KArgumentCaptor<T>.() -> Unit): KArgumentCaptor<T>

Usage Examples:

import com.nhaarman.mockitokotlin2.*

// Captor with immediate verification
val userCaptor = argumentCaptor<User> {
    verify(userService).saveUser(capture())
    // Can access captured values immediately
    assertThat(firstValue.email).isNotEmpty()
}

Nullable Argument Captors

Special argument captors for nullable types.

/**
 * Creates a KArgumentCaptor for nullable type
 * @returns KArgumentCaptor instance for capturing nullable arguments of type T
 */
inline fun <reified T : Any> nullableArgumentCaptor(): KArgumentCaptor<T?>

/**
 * Creates a KArgumentCaptor for nullable type with immediate lambda evaluation
 * @param f Lambda function applied to the created captor
 * @returns KArgumentCaptor instance for nullable type after applying the lambda
 */
inline fun <reified T : Any> nullableArgumentCaptor(f: KArgumentCaptor<T?>.() -> Unit): KArgumentCaptor<T?>

Usage Examples:

import com.nhaarman.mockitokotlin2.*

// Nullable argument captor
val nullableUserCaptor = nullableArgumentCaptor<User>()
verify(userService).updateUser(nullableUserCaptor.capture())
val capturedUser = nullableUserCaptor.firstValue // Can be null

// Nullable captor with lambda
val nullableCaptor = nullableArgumentCaptor<String> {
    verify(service).processOptionalData(capture())
    // Handle null case
    firstValue?.let { 
        assertThat(it).isNotEmpty() 
    }
}

Capture Helper Function

Utility function for capturing arguments directly.

/**
 * Alias for ArgumentCaptor.capture() with null safety
 * @param captor The ArgumentCaptor to use for capturing
 * @returns Captured value or created instance if null
 */
inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T

Usage Examples:

import com.nhaarman.mockitokotlin2.*
import org.mockito.ArgumentCaptor

// Using with standard Mockito ArgumentCaptor
val javaCaptor = ArgumentCaptor.forClass(User::class.java)
verify(userService).saveUser(capture(javaCaptor))
val capturedUser = javaCaptor.value

KArgumentCaptor Class

Kotlin wrapper for ArgumentCaptor providing enhanced functionality.

/**
 * Kotlin wrapper for ArgumentCaptor with enhanced functionality and null safety
 */
class KArgumentCaptor<out T : Any?>(
    private val captor: ArgumentCaptor<T>,
    private val tClass: KClass<*>
) {
    /**
     * The first captured value of the argument
     * @throws IndexOutOfBoundsException if the value is not available
     */
    val firstValue: T
    
    /**
     * The second captured value of the argument
     * @throws IndexOutOfBoundsException if the value is not available
     */
    val secondValue: T
    
    /**
     * The third captured value of the argument
     * @throws IndexOutOfBoundsException if the value is not available
     */
    val thirdValue: T
    
    /**
     * The last captured value of the argument
     * @throws IndexOutOfBoundsException if the value is not available
     */
    val lastValue: T
    
    /**
     * All captured values as a list
     */
    val allValues: List<T>
    
    /**
     * Captures an argument for the associated method parameter
     * @returns Captured value or created instance if null
     */
    fun capture(): T
}

Usage Examples:

import com.nhaarman.mockitokotlin2.*

val userCaptor = argumentCaptor<User>()

// Capture multiple calls
verify(userService, times(3)).saveUser(userCaptor.capture())

// Access different captured values
val firstUser = userCaptor.firstValue
val secondUser = userCaptor.secondValue  
val thirdUser = userCaptor.thirdValue
val lastUser = userCaptor.lastValue

// Access all captured values
val allUsers = userCaptor.allValues
assertThat(allUsers).hasSize(3)

// Verify properties of captured arguments
assertThat(firstUser.email).contains("@")
assertThat(allUsers).allMatch { it.age >= 18 }

Argument Captor Holder Classes

Helper classes for managing multiple argument captors.

/**
 * Holder class for 4 argument captors with component access
 */
class ArgumentCaptorHolder4<out A, out B, out C, out D>(
    val first: A,
    val second: B,
    val third: C,
    val fourth: D
) {
    operator fun component1(): A
    operator fun component2(): B  
    operator fun component3(): C
    operator fun component4(): D
}

/**
 * Holder class for 5 argument captors with component access
 */
class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
    val first: A,
    val second: B,
    val third: C,
    val fourth: D,
    val fifth: E
) {
    operator fun component1(): A
    operator fun component2(): B
    operator fun component3(): C  
    operator fun component4(): D
    operator fun component5(): E
}

Usage Examples:

import com.nhaarman.mockitokotlin2.*

// Using holder classes with destructuring
val (nameCaptor, ageCaptor, emailCaptor, activeCaptor) = 
    argumentCaptor<String, Int, String, Boolean>()

verify(userService).createUser(
    nameCaptor.capture(),
    ageCaptor.capture(),
    emailCaptor.capture(), 
    activeCaptor.capture()
)

// Access via properties
val holder = argumentCaptor<String, Int, String, Boolean>()
verify(userService).createUser(
    holder.first.capture(),
    holder.second.capture(),
    holder.third.capture(),
    holder.fourth.capture()
)

Extension Properties

Extension properties for standard Mockito ArgumentCaptor to match KArgumentCaptor functionality.

/**
 * Extension property for first captured value
 */
val <T> ArgumentCaptor<T>.firstValue: T

/**
 * Extension property for second captured value  
 */
val <T> ArgumentCaptor<T>.secondValue: T

/**
 * Extension property for third captured value
 */
val <T> ArgumentCaptor<T>.thirdValue: T

/**
 * Extension property for last captured value
 */
val <T> ArgumentCaptor<T>.lastValue: T

Usage Examples:

import com.nhaarman.mockitokotlin2.*
import org.mockito.ArgumentCaptor

// Using extensions with standard ArgumentCaptor
val javaCaptor = ArgumentCaptor.forClass(String::class.java)
verify(service, times(3)).processString(javaCaptor.capture())

val firstString = javaCaptor.firstValue
val lastString = javaCaptor.lastValue
val allStrings = javaCaptor.allValues

Types

// From org.mockito
class ArgumentCaptor<T>
interface KClass<T>

// From mockito-kotlin
class KArgumentCaptor<out T : Any?>(
    private val captor: ArgumentCaptor<T>,
    private val tClass: KClass<*>
) {
    val firstValue: T
    val secondValue: T
    val thirdValue: T
    val lastValue: T
    val allValues: List<T>
    fun capture(): T
}

class ArgumentCaptorHolder4<out A, out B, out C, out D>(
    val first: A,
    val second: B,
    val third: C,
    val fourth: D
)

class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
    val first: A,
    val second: B,
    val third: C,
    val fourth: D,
    val fifth: E
)

Install with Tessl CLI

npx tessl i tessl/maven-com-nhaarman-mockitokotlin2--mockito-kotlin

docs

argument-capturing.md

argument-matching.md

index.md

mock-creation.md

spying.md

stubbing.md

verification.md

tile.json