es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo simular el ApplicationContext en el objeto compañero en Kotlin?

Ayuda a probar una función que llama a un método de clase.
Hay una clase cuyo campo se inicializa con una cadena de métodos appContext().getBean().

class ClassA {
    private val employeeApi: EmployeeApi = appContext().getBean()
    fun execute(): List<employee> {
        return employeeApi.method()
    }
}

y por ejemplo hay una función para llamar a los métodos de clase.

    fun methodForTesting(params: ClassA.() -> Unit): List<employee> {
         return ClassA().apply(params).execute()
    }

Esta función necesita ser probada. ¿Cómo hacerlo?

  1. Abrir acceso al método en el archivo utilizando
    mockkStatic("com.company.MyFile")
  2. Crear una lista de empleados que deben ser devueltos
  3. Crear un método stub
  4. Llamar al método
  5. Verificar los datos
@Test
fun `methodForTesting mockk`() {
    mockkStatic("com.company.MyFile")
    val classA : ClassA= Mockito.mock(ClassA::class.java)
    val listEmployee: List<employee> = listOf(Employee("Ivan"))
    Mockito.`when`(classA.execute()).thenReturn(listEmployee)

    val list: List<employee> = methodForTesting(allAny())

    Assertions.assertThat(list).isEqualTo(listEmployee)
}

Si escribo así, entonces ocurre un error. ¿Cómo se puede finalizar la solución?

Error:
kotlin.UninitializedPropertyAccessException: lateinit property FIELD has not been initialized
at Mockito.when(classA.execute()).thenReturn(listEmployee) <– HERE

“`kotlin
@Configuration
@EnableConfigurationProperties(HurmaProperties::class)
class AppConfig : ApplicationContextAware {
private var applicationContext: ApplicationContext? = null

<pre><code>override fun setApplicationContext(applicationContext: ApplicationContext) {
this.applicationContext = applicationContext
appCtx = applicationContext
}

@Bean
fun restTemplateBuilder(): RestTemplateBuilder = RestTemplateBuilder()

@Bean
fun restTemplate(builder: RestTemplateBuilder): RestTemplate =
builder.build()

companion object {
@JvmStatic
lateinit var appCtx: ApplicationContext
private set
}
</code></pre>

}

fun appContext() = AppConfig.appCtx
“`

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para probar el método methodForTesting(), podemos usar el framework MockK para simular la clase ClassA y su método execute(). Aquí está la solución para finalizar el caso de prueba anterior:

    import io.mockk.every
    import io.mockk.mockkStatic
    import org.assertj.core.api.Assertions.assertThat
    import org.junit.jupiter.api.Test
    
    class TestClassA {
        // Se asume que EmployeeApi es una interfaz
        private val employeeApi = mockk<employeeapi>()
    
        @Test
        fun `methodForTesting mockk`() {
            val listEmployee: List<employee> = listOf(Employee("Ivan"))
            every { employeeApi.method() } returns listEmployee
    
            mockkStatic("com.example.package.AppConfigKt")
            every { appContext().getBean<employeeapi>() } returns employeeApi
    
            val list: List<employee> = methodForTesting(ClassA::execute)
    
            assertThat(list).isEqualTo(listEmployee)
        }
    }
    

    La solución hace lo siguiente:

    1. Creamos una instancia de EmployeeApi usando MockK y asumimos que se asigna al campo employeeApi de ClassA.
    2. La sintaxis every { ... } returns ... de MockK se utiliza para simular el comportamiento de employeeApi.method(), que devuelve una lista de empleados. Esto se usará más adelante en la prueba.
    3. Simulamos la función estática appContext().getBean<employeeapi>() que es llamada por ClassA. Esto se hace utilizando la función mockkStatic().
    4. Aplicamos el comportamiento de simulación a ClassA llamando a methodForTesting() con ClassA::execute como parámetro.
    5. Finalmente, usamos el método assertThat() de AssertJ para verificar que la lista devuelta por methodForTesting() es igual a la lista de empleados devuelta por employeeApi.method().

    Nota: asumimos que EmployeeApi es una interfaz porque llamar al mismo método en una instancia simulada de una clase concreta puede no producir el resultado deseado.

Comments are closed.