我需要一些建议用jmockit和kotlin。
(剪切)这是正在测试的我的(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)与gradle一起运行时,也会引发相同的异常。
(kt.2)通过使用kotlin的@ syntax语法,我得到了一个不同的例外:
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并使用!操作员导致了一个工作测试..。但这不是惯用的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));
}
}你用kotlin和jmockit玩得更成功吗?
发布于 2015-02-24 15:34:55
我不认为您将能够使用来自Kotlin的JMockit (或者大多数其他JVM替代语言,可能是Groovy除外),无论如何也不能可靠地使用。
原因是: 1) JMockit的开发没有考虑到这些语言,也没有用它们进行测试;2)这些语言在编译为字节码时会产生额外的或不同的构造,可能会混淆像JMockit这样的工具;此外,它们通常会插入对自己内部API的调用,这也可能会阻碍它们的开发。
在实践中,替代语言倾向于开发自己的测试/模拟/等等工具,这些工具不仅对该语言及其运行时运行良好,而且还让您充分利用该语言的优势。
就我个人而言,即使我能认识到这些语言带来的许多好处(我特别喜欢Kotlin),我还是宁愿坚持使用Java ( Java继续发展--参见Java 8)。事实是,到目前为止,Java的广泛使用还没有替代的JVM语言,而且(IMO)它们永远也不会。
发布于 2015-02-26 17:42:55
我们做了一些实验,发现您可以定义如下特殊功能:
fun uninitialized<T>() = null as T然后像这样使用它:
[Mocked] val dateTime : LocalDateTime = uninitialized()您也可以使用它而不是Matchers.any()来达到同样的效果。我们将考虑将其添加到编译器或标准库中。
https://stackoverflow.com/questions/28696399
复制相似问题