Java Eclipse中同步方法超时的Mockito验证失败
当使用MockitoJava Eclipse中同步方法超时的Mockito验证失败,java,eclipse,mockito,synchronized,Java,Eclipse,Mockito,Synchronized,当使用Mockitoverify并超时等待异步方法调用时,如果方法被同步,则有时会失败 我在Eclipse的多个版本中观察到了这种效果,包括2020-06(4.16.0),以及Mockito 3.1.0和3.4.6。下面的例子说明了这个问题(为了简单起见,测试和被测试的主题都在同一个类中)。为什么会失败 import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.
verify
并超时等待异步方法调用时,如果方法被同步,则有时会失败
我在Eclipse的多个版本中观察到了这种效果,包括2020-06(4.16.0),以及Mockito 3.1.0和3.4.6。下面的例子说明了这个问题(为了简单起见,测试和被测试的主题都在同一个类中)。为什么会失败
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class A {
@Mock
private A a;
public synchronized void f() {
// Do stuff
}
@Test
void test() {
// Call a.f() asynchronously and with a small delay
// (to make the test thread yield).
new Thread(() -> {
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
a.f();
}).start();
// This verification fails, but it should pass.
Mockito.verify(a, Mockito.timeout(2000)).f();
}
}
值得注意的是:
- 这种效果不是完全可以重现的。事实上,我的现实生活中的例子在某些计算机上从未失败,而在其他计算机上却总是失败,这表明了一种竞争条件
- 删除
关键字可以解决问题,即使将其替换为方法体中的synchronized
块也是如此synchronized(this)
- 如果包含synchronized方法的类实现了一个接口,那么模拟该接口而不是具体的类可以解决这个问题
- 在上面的示例中,删除睡眠,从而增加了在调用
之前完成对verify
的调用的可能性,从而解决了问题f
- 该行为可疑地类似于此处描述(并可能已解决)的问题: