2015-02-24 18 views
5

Ich brauche ein paar Ratschläge JMockit mit Kotlin verwenden.Mit Kotlin mit JMockit

(CUT) Dies ist mein (Java) Klasse im Test:

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

(J.1) Dies ist ein funktionierendes Java-Test-Klasse

@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) jedoch die entsprechende Klasse Kotlin löst eine Ausnahme

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

Ausnahme:

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) 

Die gleiche Ausnahme ausgelöst wird, wenn sie mit gradle laufen.

(kt.2) die @Mocked Syntax mit Kotlin Verwendung Ich bin eine andere Ausnahme bekommen:

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

Ausnahme:

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) 

bearbeiten 20.150.224 vielleicht Zusammenhang damit auf „Für Ein Mock-Feld, eine Instanz des deklarierten Typs wird automatisch von JMockit erstellt und dem Feld zugewiesen, sofern es nicht endgültig ist. " (Von http://jmockit.org/tutorial/BehaviorBasedTesting.html)

(kt.3) jedoch das Val an var ändern und unter Verwendung !! Betreiber führen zu einem Arbeits Test ... aber das ist nicht idiomatischer Kotlin Code:

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

Haben Sie mit JMockit mehr Erfolg mit Kotlin haben?

Antwort

0

Ich glaube nicht, Sie in der Lage sein werden JMockit von Kotlin zu verwenden (oder die meisten anderen JVM alternative Sprachen, mit der möglichen Ausnahme von Groovy), nicht zuverlässig sowieso.

Die Gründe dafür sind, dass 1) JMockit nicht mit solchen Sprachen im Auge entwickelt wurde, und ist nicht mit ihnen getestet; und 2) erzeugen diese Sprachen, wenn sie in Bytecode kompiliert werden, zusätzliche oder andere Konstrukte, die ein Werkzeug wie JMockit verwirren können; Außerdem fügen sie normalerweise Aufrufe in ihre eigenen internen APIs ein, die ebenfalls stören können.

In der Praxis alternative Sprachen neigen dazu, ihre eigenen Tests/spöttischen/etc zu entwickeln. Werkzeuge, die nicht nur für diese Sprache und ihre Laufzeit gut funktionieren, sondern auch die Stärken der Sprache voll ausnutzen.

Persönlich, obwohl ich die vielen Vorteile erkennen kann, die solche Sprachen bringen (und ich mag besonders Kotlin), würde ich lieber bei Java bleiben (das sich weiter entwickelt - siehe Java 8). Tatsache ist, so weit keine Alternative JVM Sprache ist sogar weit von Javas weit verbreiteter Verwendung gekommen, und (IMO) werden sie nie.

+0

> Ich würde lieber bei Java bleiben (was sich weiter entwickelt - siehe Java 8) Ich möchte nur darauf hinweisen, dass dies unter Android nicht der Fall ist. –

+0

@JaysonMinard Rogerio ist der Autor von jmockit – Novaterata

0

Wir haben ein wenig experimentiert und festgestellt, dass Sie spezielle Funktion wie folgt definieren:

fun uninitialized<T>() = null as T 

und es dann wie folgt verwenden:

[Mocked] val dateTime : LocalDateTime = uninitialized() 

Sie können auch stattdessen von Matchers.any() für den gleichen Effekt. Wir werden es in Betracht ziehen, es dem Compiler oder der Standardbibliothek hinzuzufügen.

+0

Die Syntax für Anmerkungen hat sich geändert, im obigen Beispiel wäre '[Mocked]' nun '@ Mocked' –