作为我的单元测试的一部分,我试图模拟Thread.class isAlive()方法使用Mockito返回true。以下是我的代码:
final Thread mockThread = Mockito.mock(Thread.class);
Mockito.when(mockThread.isAlive()).thenReturn(true);
这在第二行给出了以下例外:
Exception in thread "main" org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
我已经多次使用Mockito而没有问题。模拟Thread.class有一些问题吗?我没有运气就四处寻找。
答案 0 :(得分:3)
Thread.isAlive()
修饰符声明 final
。它不能被Mockito 1嘲笑
使用添加this feature的Powermock或Mockito 2:
很长一段时间,当Mockito拒绝时,我们的用户都难以置信 嘲笑最后一堂课。 ... 最终类和方法的模拟是一个孵化,选择加入的功能
或者另一种方式:改变对班级进行单元测试的方式。
您真的需要依靠isAlive()
进行单元测试吗?
如果你确实需要它,你也可以使用一个包装类来组成一个Thread
实例,并将处理委托给组合Thread
。
例如,这可以实现Runnable
通过这种方式,您可以自然地模拟此包装类的isAlive()
方法。
答案 1 :(得分:2)
正如其他人所指出的,Thread的isAlive方法是最终的,因此不能(也可能不应该)使用Mockito进行模拟。
一个简单的解决方法是在我的单元测试类中使用run()方法创建一个私有的Runnable类,该方法只调用this.wait()。
private class TestRunnable implements Runnable {
@Override
public void run() {
synchronized(this) {
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("Interrupted!");
}
}
}
}
然后我可以使用this的实例在单元测试中创建一个线程,isAlive()方法将始终返回true。
final TestRunnable testRunnable = new TestRunnable();
final Thread expectedThread = new Thread(testRunnable);
expectedThread.start();
然后在测试中......
assertTrue(expectedThread.isAlive());
最后,要清理线程,只需在Runnable实例上调用notify()(当然,当JUnit完成时线程也将结束)
synchronized(testRunnable) {
testRunnable.notifyAll(); // kill the Runnable (prob not necessary)
}
答案 2 :(得分:2)
我给你一个完全不同的观点:摆脱与生产代码中的线程完全交互。
事情是:Thread是一个非常低级抽象的多线程。 10,15年前我们只有 主题,并因此被迫使用它们。
但是现在,你有很多种抽象在更高层次上工作,比如ExecutorServices和Futures,以及Promises,......
这可能听起来很奇怪 - 但是你可能更有帮助的是回过头来考虑 not 使用线程,就像你今天使用它们一样。您可以看到,Same-Thread-Executors等内容允许您将多线程代码转换为单个线程进行测试 - 只需提供不同的服务来执行任务即可。
这就是你应该在2017年努力的抽象层次 - 你不应该浪费时间去嘲笑低级别的最终方法!
答案 3 :(得分:1)
看起来Thread.isAlive方法是final,并且不能用Mockito模拟最终方法。