我做错了什么,抛出了一个异常而不是显示一个失败,或者我不应该在线程内有Assert?
@Test
public void testComplex() throws InterruptedException {
int loops = 10;
for (int i = 0; i < loops; i++) {
final int j = i;
new Thread() {
@Override
public void run() {
ApiProxy.setEnvironmentForCurrentThread(env);//ignore this
new CounterFactory().getCounter("test").increment();//ignore this too
int count2 = new CounterFactory().getCounter("test").getCount();//ignore
assertEquals(j, count2);//here be exceptions thrown. this is line 75
}
}.start();
}
Thread.sleep(5 * 1000);
assertEquals(loops, new CounterFactory().getCounter("test").getCount());
}
堆栈追踪
Exception in thread "Thread-26" junit.framework.AssertionFailedError: expected:<5> but was:<6>
at junit.framework.Assert.fail(Assert.java:47)
at junit.framework.Assert.failNotEquals(Assert.java:277)
at junit.framework.Assert.assertEquals(Assert.java:64)
at junit.framework.Assert.assertEquals(Assert.java:195)
at junit.framework.Assert.assertEquals(Assert.java:201)
at com.bitdual.server.dao.ShardedCounterTest$3.run(ShardedCounterTest.java:77)
5条答案
按热度按时间myss37ts1#
JUnit框架只捕获运行测试的主线程中的Assert错误。它不知道来自新衍生线程中的异常。为了正确地执行它,您应该将线程的终止状态通知给主线程。您应该正确地同步线程,并使用某种共享变量来指示嵌套线程的结果。
编辑:
下面是一个通用的解决方案,可以帮助:
您应该在构造函数中传递runnable,然后您只需调用start()来激活,并调用test()来验证。如果需要的话,test方法将等待,并在主线程的上下文中抛出Assert错误。
cotxawn72#
对Eyal Schneider's answer的一个小改进:
ExecutorService
允许提交Callable
,并且返回的Future
会重新引发任何引发的异常或错误。因此,该测试可写成:
tktrz96b3#
在涉及多个工作线程的情况下,例如在最初的问题中,仅仅加入其中一个是不够的。理想情况下,您将希望等待所有工作线程完成,同时仍然向主线程报告Assert失败,如Eyal的答案所示。
下面是一个简单的例子,说明如何使用我的ConcurrentUnit来实现这一点:
zaqlnxep4#
我最终使用了这个模式,它可以同时处理Runnables和Threads。它的灵感主要来自于@ EyalSchneider的回答:
pprl5pva5#
JUnit抛出的AssertionError是Throwable的扩展,它与Exception具有相同的父级。您可以捕获线程的失败Assert,然后将其保存在静态字段中,最后在主线程中检查是否其他线程的某个Assert失败。
首先,创建静态字段
其次,将Assert Package 在try/catch中,并捕获AssertionError
最后,在主线程中检查该字段