ArgumentMatchers.any no debe ser nulo

5 minutos de lectura

avatar de usuario
Ana Koridze

estoy tratando de probar ViewModel para asegurarse de que livedata se actualice correctamente. Sin embargo al usar ArgumentMatchers.any() falla con IllegalStateException dicho:

ArgumentMatchers.any(mViewModel.CountSubscriber::class.java) no debe ser nulo

@Test
fun emitValueIfCountIs7() {
    doAnswer { invocation: InvocationOnMock ->
        val subscriber: mViewModel.CountSubscriber = invocation.getArgument(0)
        subscriber.onNext(7)
        null
    }.`when`(countUseCase).execute(
        ArgumentMatchers.any(mViewModel.CountSubscriber::class.java),
        ArgumentMatchers.any(Parameters::class.java)
    )
    
    // When
    mViewModel.getCount()
    
    // Verify
    assert(mViewModel.countResponse.value != null)
}

Estoy usando Kotlin y tengo las siguientes dependencias:

testImplementation 'junit:junit:4.12'
testImplementation "org.mockito:mockito-inline:2.23.4"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"

Aquí están mis importaciones:

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.nhaarman.mockitokotlin2.doAnswer
import io.reactivex.Observable
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.invocation.InvocationOnMock

Lo extraño es que solía funcionar antes, y no sé qué ha pasado que podría afectar esto.

  • ¿Puede publicar sus importaciones? IIRC esto puede suceder cuando se usa el comparador que no es kotlin con código kotlin.

    – fweigl

    7 dic 2019 a las 21:11

  • Actualicé la pregunta con importaciones.

    – Ana Koridze

    7 dic 2019 a las 21:53

  • ArgumentMatchers.any(Class type) siempre devuelve nulo sin importar el objeto que estoy tratando de hacer coincidir

    – Ana Koridze

    8 de diciembre de 2019 a las 10:43

  • Tenías razón, reemplacé las dependencias de org.mockito con las de com.nhaarman.mockitokotlin2 y ¡ahora funciona!

    – Ana Koridze

    8 de diciembre de 2019 a las 11:01

avatar de usuario
Nabzi

Lograr que los comparadores trabajen con Kotlin puede ser un problema. Si tiene un método escrito en kotlin que no acepta un parámetro anulable, entonces no podemos hacer coincidir con él usando Mockito.any(). Esto se debe a que puede devolver void y esto no se puede asignar a un parámetro que no admite valores NULL.

Si el método que se empareja está escrito en Java, entonces creo que funcionará ya que todos los objetos de Java son implícitamente anulables.

Una posible solución sería utilizar una biblioteca como Mockito-kotlin
Pero usted mismo puede resolver este problema fácilmente con unas pocas líneas de código.

Si necesita escribir alguno (tipo: Clase)

private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)

O

Puede usar este comparador en lugar de Matchers.any() :

object MockitoHelper {
fun <T> anyObject(): T {
    Mockito.any<T>()
    return uninitialized()
}
@Suppress("UNCHECKED_CAST")
   fun <T> uninitialized(): T = null as T
}

y use MockitoHelper.anyObject() en vez de any() en tus pruebas de kotlin.

Puedes encontrar más información en este post: Usando Mockito con Kotlin

Hay una discusión sobre posibles soluciones en esta publicación: ¿Es posible usar Mockito en Kotlin?

  • Muchas gracias por esta explicación y estas respuestas. La primera clase escrita fn funcionó perfectamente para mí.

    – orfeo

    31 oct 2021 a las 19:12

avatar de usuario
Haomin

La solución correcta se menciona en la sección de comentarios de la pregunta de @Ana Koridze. Sí, si está usando Koltin + mockitoKotlin. Asegúrese de que está utilizando la siguiente importación:

1 – Usando el Mockito-kotlin:

import org.mockito.kotlin.any de Mockito-kotlin en lugar de
import org.mockito.Mockito.any

testImplementation "org.mockito.kotlin:mockito-kotlin:$mockito_kotlin_version"

2 – O si está utilizando una versión anterior de mockito kotlin original creada por nhaarman antes de la interacción

import com.nhaarman.mockitokotlin2.any de Mockito-kotlin de nhaaram en lugar de import org.mockito.Mockito.any

testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:$mockito_kotlin2_version"

Por cierto, si está utilizando Android Studio o IntelliJ IDEA. la any() de la biblioteca de mockitokotlin debe ser italic por estilo/esquema de color predeterminado.


Observe la any() al final de la línea. Esto es de maqueta

ingrese la descripción de la imagen aquí

Y aquí está el any() de maqueta

ingrese la descripción de la imagen aquí

Gracias @Sattar por la edición recomendada.

  • lo unico que me funciono. Gracias @haomin

    – Nouman Ch.

    10 de marzo de 2021 a las 18:54

  • ¡Tuve el mismo problema y luego leí su respuesta y verifiqué mis importaciones y ahora funciona! ¡Gracias!

    – Maroung

    6 de octubre de 2021 a las 10:18

  • Salvaste mi día. ¡Gracias!

    – Arkadi

    8 de noviembre de 2021 a las 12:41

usar Mockito-kotlin

testImplementation "org.mockito.kotlin:mockito-kotlin:$mockito_kotlin_version"

esto usará cualquiera que funcione para kotlin ya que esta es una librería contenedora para Mockito pero para kotlin

Mockito-kotlin ha agregado soporte para argumentos anulables con anyOrNull()

        `when`(myMock.doesThis(any(), anyOrNull())).thenReturn(someObject)

avatar de usuario
bastami82

Esto es lo que funcionó para mí,

  1. o reemplazó todos los genéricos any()s , con un anyTYPE() específico, es decir anyInt(), anyList() etc. de core lib org.mockito:mockito-core y soluciona el problema (de anulabilidad), parece que las definiciones específicas con tipo pueden manejar nulo. esta opción no requiere que importe ninguna biblioteca adicional

o

  1. si realmente necesita usar el tipo genérico any() agregue esta extensión lib oficial de Mckito https://github.com/mockito/mockito-kotlin y asegúrese de usar el any() de esta biblioteca (asegurándose de que sus importaciones tengan esto en ella) import org.mockito.kotlin.any)

Sugiero comenzar a usar MockK lib https://github.com/mockk/mockk en lugar de Mockito ya que es un Mock biblioteca para Kotlin = MockK)

sin embargo, si le da pereza cambiar ahora mismo o tal vez esté lidiando con pruebas heredadas (como en mi caso :), esto también debería solucionar su problema.

avatar de usuario
Gad Wissberg

Para mí, todas las soluciones anteriores no fueron suficientes, además de eso, tuve que marcar el método llamado como un método ‘abierto’. De acuerdo a esto:
https://github.com/mockito/mockito-kotlin/wiki/Parameter-specified-as-non-null-is-null
El método es definitivo y Mockito no pudo burlarse de él, así que tuve que agregar ‘abierto’.

¿Ha sido útil esta solución?