实施全局超时时出错

时间:2015-01-07 11:33:57

标签: testing junit

timeout is set for test method和未设置时,Junit中的测试运行方式是否有任何架构差异?

当我实现超时时,即使测试没有超时,我也会遇到安全错误(数据安全系统需要创建和有效的ApplSession)(与会话相关)。 解决问题的方法是什么? 这不是完整的堆栈跟踪,但这是我可以分享的内容:

         sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
         sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
         sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
         java.lang.reflect.Method.invoke(Method.java:597)
         org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
         org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
         org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
         org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
         org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
         org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
 org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:62)

1 个答案:

答案 0 :(得分:0)

是的,JUnit以不同的方式运行带有超时注释的测试。我也经历过这一点。

据我所知,JUnit在分离的线程中执行每个测试用例超时,以便在超时发生时停止/终止它。 因此,测试用例中的代码可能具有与预期不同的上下文,或者可能在会话上下文之外。

如何解决问题:

  • 创建一个静态方法,用@BeforeClass注释它,检索当前会话并将其存储到静态字段(这必须在测试用例之外完成)
  • 使用静态字段的(服务器)会话作为上下文创建一个runnable,在runnable中实现测试逻辑并执行它
  • 确保将runnable中抛出的断言异常重新抛出到测试用例方法

代码看起来像这样(取决于你的框架):

private static ISession s_session;

@BeforeClass
public static void beforeClass() throws ProcessingException {
  s_session = AbstractServerSession.get();
}

@Test(timeout = 5000)
public void testX() throws Throwable {
  JobForServerTestcaseWithTimeout job = new JobForServerTestcaseWithTimeout(s_session) {
    @Override
    protected void executeTest() throws Exception {
      //put the test logic here
      assertTrue(true);
    }
  };

  job.runAndCheckAssertions();
}

JobForServerTestcaseWithTimeout是一个带有服务器会话的线程,它在try-catch-block中运行executeTest()方法。它捕获第一个异常(失败的断言导致AssertionError)并将其存储到成员变量中。 runAndCheckAssertions()检查是否发生了异常,如果是,则会重新抛出异常。

实际测试逻辑位于executeTest()的实现中。但是,executeTest()只能调用方法testXInternal()(可以直接在测试类中实现),以使代码更具可读性。