2015-02-24 27 views
5

Potrzebuję porady, używając jmockita z kotlinami.Używanie kotlin z jmockitem

(CUT) Jest to moja klasa (Java) w ramach badania:

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

(J.1) Jest to działa klasa Test 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) Jednakże, odpowiednia klasa Kotlin zgłasza wyjątek

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

Wyjątek

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) 

Ten sam wyjątek jest generowany podczas uruchamiania ze stopniem.

(kt.2) Korzystanie ze składni @Mocked Kotlin Dostaję inny wyjątek:

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

Wyjątek:

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 może jest to związane z „Dla pole próbne, wystąpienie zadeklarowanego typu zostanie automatycznie utworzone przez JMockit i przypisane do tego pola, o ile nie jest ostateczne. " (od http://jmockit.org/tutorial/BehaviorBasedTesting.html)

(kt.3) Jednakże, zmieniając val na var i używając a !! Operator prowadzi do testu pracy ... ale to nie jest idiomatyczne kod 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)); 
    } 
} 

Czy mają więcej sukcesów używając Kotlin z jmockit?

Odpowiedz

0

Nie sądzę, że będziesz w stanie używać JMockit z Kotlin (lub większości innych języków JVM z możliwym wyjątkiem Groovy), a nie niezawodnie.

Powody są następujące: 1) JMockit nie został opracowany z myślą o takich językach i nie jest testowany wraz z nimi; oraz 2) te języki, po skompilowaniu do kodu bajtowego, tworzą dodatkowe lub różne konstrukcje, które mogą zmylić narzędzie takie jak JMockit; również zwykle wstawiają wywołania do własnych wewnętrznych API, które również mogą przeszkadzać.

W praktyce języki alternatywne mają tendencję do rozwijania własnych testów/kpiny/etc. narzędzia, które nie tylko dobrze sprawdzają się w przypadku tego języka i jego środowiska wykonawczego, ale także pozwalają w pełni wykorzystać zalety języka.

Osobiście, mimo że mogę rozpoznać wiele korzyści, jakie przynoszą takie języki (a szczególnie podoba mi się Kotlin), wolałbym trzymać się Javy (która wciąż ewoluuje - patrz Java 8). Faktem jest, że do tej pory alternatywny język JVM nie był tak szeroko rozpowszechniony w użyciu Javy i (IMO), że nigdy tego nie zrobią.

+0

> Wolałbym trzymać się Javy (która wciąż ewoluuje - patrz Java 8) Chcę tylko zauważyć, że nie jest to prawdą na Androida. –

+0

@JaysonMinard Rogerio jest autorem jmockit – Novaterata

0

Mamy eksperymentował trochę i okazało się, że można zdefiniować specjalną funkcję tak:

fun uninitialized<T>() = null as T 

a następnie używać go tak:

[Mocked] val dateTime : LocalDateTime = uninitialized() 

Można również użyć go zamiast Matchers.any() dla tego samego efektu. Rozważymy dodanie go do kompilatora lub biblioteki standardowej.

+0

Zmieniła się składnia adnotacji, w powyższym przykładzie '[wyśmiewane]' będzie teraz '@ Mocked' –