为什么我的单元测试在调试模式下成功但在正常运行时失败?
public class ExecutorServiceTest extends MockitoTestCase{
private int numThreads;
private ExecutorService pool;
private volatile boolean interruptedBitSet;
@Override
public void setUp() {
numThreads = 5;
pool = Executors.newFixedThreadPool(numThreads);
}
class TaskChecksForInterruptedBit implements Callable<String> {
@Override
public String call() throws Exception {
interruptedBitSet = false;
while (!Thread.currentThread().isInterrupted()) {
}
interruptedBitSet = Thread.currentThread().isInterrupted();
return "blah";
}
}
public void testCancelSetsInterruptedBitInCallable() throws Exception {
interruptedBitSet = false;
final Future<String> future =
pool.submit(new TaskChecksForInterruptedBit());
final boolean wasJustCancelled = future.cancel(true);
assertTrue(wasJustCancelled);
// Give time for the thread to notice the interrupted bit and set the flag
Thread.sleep(5000);
// This succeeds when stepping through w/ a debugger, but fails when running
// the test straight. WHY?
assertTrue(interruptedBitSet);
assertTrue(future.isDone());
assertTrue(future.isCancelled());
}
}
答案 0 :(得分:3)
原因几乎可以肯定,调试器中的断点正在暂停主线程,但没有任何后台线程 - ExecutorService中的线程。在eclipse中调试时,您可以更改断点以暂停所有线程,而不仅仅是主线程。
当没有调试任务的提交时,立即取消的速度非常快,以至于您甚至在运行一次之前就取消了该任务。尝试在这些行之间添加睡眠延迟:
final Future<String> future = pool.submit(new TaskChecksForInterruptedBit());
Thread.sleep(1000);
final boolean wasJustCancelled = future.cancel(true);
答案 1 :(得分:2)
我知道这已经过时但我遇到了同样的问题。 我的问题是我有一个 IEnumerable ,我正在枚举并检查输出。
运行单元测试时, IEnumerable 返回调试时的不同顺序。这是 IEnumerable 的本质,只需添加 OrderBy 子句即可解决我的问题。
我希望这可以帮助那些人,因为这可能是一个令人沮丧的问题。
答案 2 :(得分:1)
您必须确保您的任务实际开始运行。它甚至可能在有机会之前被取消。
public class ExecutorServiceTest {
private int numThreads;
private ExecutorService pool;
private volatile boolean interruptedBitSet;
private static final CountDownLatch latch = new CountDownLatch(1);
@Before
public void setUp() {
numThreads = 5;
pool = Executors.newFixedThreadPool(numThreads);
}
class TaskChecksForInterruptedBit implements Callable<String> {
@Override
public String call() throws Exception {
interruptedBitSet = false;
latch.countDown();
while (!Thread.currentThread().isInterrupted()) {
System.out.println(System.currentTimeMillis());
}
System.out.println("haha");
interruptedBitSet = Thread.currentThread().isInterrupted();
return "blah";
}
}
@Test
public void testCancelSetsInterruptedBitInCallable() throws Exception {
final Future<String> future =
pool.submit(new TaskChecksForInterruptedBit());
interruptedBitSet = false;
latch.await();
final boolean wasJustCancelled = future.cancel(true);
Assert.assertTrue(wasJustCancelled);
// Give time for the thread to notice the interrupted bit and set the flag
Thread.sleep(5000);
// This succeeds when stepping through w/ a debugger, but fails when running
// the test straight. WHY?
Assert.assertTrue(interruptedBitSet);
Assert.assertTrue(future.isDone());
Assert.assertTrue(future.isCancelled());
}
}
答案 3 :(得分:0)
您应该在终止主线程
之前检查所有线程是否死亡private void shutdownExecutionService(ExecutorService executorService) {
if (executorService != null) {
try {
executorService.shutdown();
while (!executorService.awaitTermination(10, TimeUnit.HOURS)) {
logger.info("Awaiting completion of threads.");
}
} catch (final InterruptedException e) {
logger.error("Error while shutting down threadpool", e);
}
}
}
答案 4 :(得分:0)
我在从在线课程上完成家庭作业时遇到了类似的问题。我添加到构建路径的课程中的分级程序使用了JUnit4,我的Eclipse版本将JUnit5添加到任何新的测试用例中。我已经创建了一个新的Java项目并将JUnit5添加到我没有分级器的测试用例的构建浴中,并为我修复了它。希望这会有所帮助。