Usando kotlin con jmockit

Necesito algunos consejos usando jmockit con kotlin.

(CUT) Esta es mi class (Java) bajo testing:

public final class NutritionalConsultant { public static boolean isLunchTime() { int hour = LocalDateTime.now().getHour(); return hour >= 12 && hour <= 14; } } 

(j.1) Esta es una class de testing de Java que funciona

 @RunWith(JMockit.class) public class NutritionalConsultantTest { @Test public void shouldReturnTrueFor12h(@Mocked final LocalDateTime dateTime) { new Expectations() {{ LocalDateTime.now(); result = dateTime; dateTime.getHour(); result = 12; }}; boolean isLunchTime = NutritionalConsultant.isLunchTime(); assertThat(isLunchTime, is(true)); } } 

(kt.1) Sin embargo, la class kotlin correspondiente arroja una exception

 RunWith(javaClass<JMockit>()) public class NutritionalConsultantKt1Test { Test public fun shouldReturnTrueFor12h(Mocked dateTime : LocalDateTime) { object : Expectations() {{ LocalDateTime.now(); result = dateTime; dateTime.getHour(); result = 12; }} val isLunchTime = NutritionalConsultant.isLunchTime() assertThat(isLunchTime, eq(true)); } } 

Excepción:

 java.lang.Exception: Method shouldReturnTrueFor12h should have no parameters at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:408) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:41) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

La misma exception se produce cuando se ejecuta con gradle.

(kt.2) Usando la syntax @Mocked con kotlin, recibo una exception diferente:

 RunWith(javaClass<JMockit>()) public class NutritionalConsultantKt2Test { Mocked var dateTime : LocalDateTime by Delegates.notNull() Test public fun shouldReturnTrueFor12h() { object : Expectations() {{ LocalDateTime.now(); result = dateTime; dateTime.getHour(); result = 12; }} val isLunchTime = NutritionalConsultant.isLunchTime() assertThat(isLunchTime, eq(true)); } } 

Excepción:

 java.lang.IllegalArgumentException: Final mock field "dateTime$delegate" must be of a class type at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

edit 20150224 tal vez esto esté relacionado con "Para un campo simulado, JMockit creará automáticamente una instancia del tipo declarado y se le asignará al campo, siempre que no sea final". (de http://jmockit.org/tutorial/BehaviorBasedTesting.html )

(kt.3) Sin embargo, cambiando el valor a var y usando un !! el operador lleva a una testing de trabajo … pero esto no es un código idiomático de kotlin:

 RunWith(javaClass<JMockit>()) public class NutritionalConsultantKt3Test { Mocked var dateTime : LocalDateTime? = null Test public fun shouldReturnTrueFor12h() { object : Expectations() {{ LocalDateTime.now(); result = dateTime; dateTime!!.getHour(); result = 12; }} val isLunchTime = NutritionalConsultant.isLunchTime() assertThat(isLunchTime, eq(true)); } } 

¿Tuvo más éxito usando kotlin con jmockit?

No creo que puedas usar JMockit de Kotlin (o la mayoría de los otros lenguajes alternativos de JVM, con la posible exception de Groovy), no confiable de todos modos.

Las razones son que 1) JMockit no se desarrolló teniendo en count dichos idiomas, y no se testing con ellos; y 2) estos lenguajes, cuando se comstackn en bytecode, producen construcciones adicionales o diferentes que pueden confundir una herramienta como JMockit; también suelen insert llamadas a sus propias API internas, lo que también puede ser un obstáculo.

En la práctica, los lenguajes alternativos tienden a desarrollar sus propias testings / burlas / etc. herramientas, que no solo funcionan bien para ese idioma y su time de ejecución, sino que también le permiten aprovechar al máximo las fortalezas del idioma.

Personalmente, aunque puedo reconocer los muchos beneficios que brindan estos idiomas (y particularmente me gusta Kotlin), preferiría quedarme con Java (que sigue evolucionando, vea Java 8). El hecho es que, hasta ahora, ningún lenguaje JVM alternativo se ha acercado demasiado al uso generalizado de Java, y (IMO) nunca lo harán.

Hemos experimentado un poco y descubrimos que puedes definir una function especial como esta:

 fun uninitialized<T>() = null as T 

y luego usarlo así:

 [Mocked] val dateTime : LocalDateTime = uninitialized() 

También puede usarlo en lugar de Matchers.any() para el mismo efecto. Consideraremos agregarlo al comstackdor o biblioteca estándar.

  • Array Int bidimensional en Kotlin
  • Carga GIF usando la versión 4.2.0 de deslizamiento en Kotlin
  • Cómo implementar la function abstracta en las constantes de Enum
  • android - Retrofit call void con Kotlin
  • Parámetro constructor de Kotlin sin getter
  • IntelliJ importa Java Boolean y luego arroja un error
  • Llamar al constructor de super class en Kotlin, Super no es una expresión
  • Comprobación de conectividad no funciona en Android Oreo Kotlin
  • Kotlin: function abstracta con tipo de retorno genérico
  • Cómo convertir código JS a Kotlin sin la palabra key 'nueva'
  • ¿Qué significa el código "val jsonObj = json como JsonObject" en Kotlin?