2015-02-24 2 views
5

Мне нужен совет с помощью jmockit с kotlin.Использование kotlin с jmockit

(CUT) Это мой (Java) класс под тест:

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

(J.1) Это рабочий класс тестирования Java

@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) Однако, соответствующий класс Kotlin генерирует исключение

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)); 
    } 
} 

исключение:

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) 

Такое же исключение выбрасывается при работе с градиентом.

(kt.2) Используя @Mocked синтаксис с Котлин я получаю другое исключение:

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)); 
    } 
} 

Исключение:

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) 

редактировать 20150224 может быть, это связано с «Для ложное поле, экземпляр объявленного типа будет автоматически создан JMockit и назначен в поле, если он не является окончательным ». (от http://jmockit.org/tutorial/BehaviorBasedTesting.html)

(kt.3) Однако, изменив значение val на var и используя !! Оператор ведет к рабочему испытанию ... но это не идиоматическое код Котлин:

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)); 
    } 
} 

Вы имели больше успеха, используя Котлин с JMockit?

ответ

0

Я не думаю, что вы сможете использовать JMockit от Kotlin (или большинства других альтернативных языков JVM, за исключением, возможно, Groovy), но не надежно.

Причины таковы: 1) JMockit не был разработан с учетом таких языков и не тестировался с ними; и 2) эти языки при компиляции в байт-код создают дополнительные или разные конструкции, которые могут смутить инструмент, такой как JMockit; также они обычно вставляют вызовы в свои собственные API-интерфейсы, которые также могут мешать.

На практике альтернативные языки имеют тенденцию разрабатывать собственное тестирование/издевательство и т. Д. инструменты, которые не только хорошо подходят для этого языка и его среды исполнения, но также позволяют в полной мере использовать преимущества языка.

Лично я понимаю, что многие преимущества, которые такие языки приносят (и мне особенно нравится Kotlin), я бы предпочел придерживаться Java (который продолжает развиваться - см. Java 8). Дело в том, что no альтернативный язык JVM пришел даже близко к распространению Java, и (IMO) они никогда не будут.

+0

> Я бы предпочел придерживаться Java (который продолжает развиваться - см. Java 8) Просто хочу отметить, что это не так на Android. –

+0

@JaysonMinard Rogerio является автором jmockit – Novaterata

0

Мы экспериментировали немного, и обнаружил, что вы можете определить специальную функцию, как это:

fun uninitialized<T>() = null as T 

, а затем использовать его как это:

[Mocked] val dateTime : LocalDateTime = uninitialized() 

Вы можете также использовать его вместо Matchers.any() для того же эффекта. Мы рассмотрим возможность добавления его в компилятор или стандартную библиотеку.

+0

Синтаксис аннотаций изменился, в приведенном выше примере '[Mocked]' теперь будет '@ Mocked' –