Java/Junit中的异步单元测试-一个非常简单但不成功的例子

n7taea2i  于 2022-11-11  发布在  Java
关注(0)|答案(2)|浏览(237)

在JavaScript中(例如使用Mocha),我可以编写异步单元测试,在最终回调中Assert内容。
这是通过将一个标记函数(通常称为done)作为参数传递给测试方法来实现的。
当函数被调用时,测试框架知道测试已经完成。
例如:

it('succeeds or fails in the last callback', function(done) {

      var deferred = Q.defer();
      setTimeout(function() { deferred.resolve('expected'); }, 500);

      deferred.promise.then(function(result) {
          assertEquals('expected', result);
          done();  // end of test
      });

  });

我发现Junit并不适合这样的场景。首先,测试方法不能处理参数,无论如何,如果我尝试例如:

@Test
  public void testAssertionInsideContinuation() {

      Long now = System.currentTimeMillis();
      System.out.println("TimeMillis=" + now);

      CompletableFuture fut = new CompletableFuture();

      Executors.newScheduledThreadPool(1)
          .schedule(() -> { fut.complete("whatever"); }, 500, TimeUnit.MILLISECONDS);

      fut.thenRun(() -> {
          long then = System.currentTimeMillis();
          System.out.println("TimeMillis=" + then);
          assertTrue(then - now >= 500);
      });
  }

第二个println将不被执行,因为测试在很久以前已经愉快地完成了。
如果我作弊并在测试方法的末尾放置一个Thread.currentThread().sleep(500);,那么未来就有机会完成,并执行Assert+第二个打印输出。
我有几个问题:

  • 什么是最简单的Java设置,我可以在其中验证回调/延续/thenables(您可以随意调用它们)中的Assert,而不必阻塞测试?
  • 我必须完全给予Junit吗?
  • 是否有一个主流的测试框架(TestNG,也许?2)允许用这种方式编写异步单元测试?

顺便说一句,如果有人能建议我一种不用ScheduledFuture来编写这个Java示例测试的方法,我也会很感激。我已经用supplyAsync做了一些实验,但没有真正确定解决方案。

r7knjye2

r7knjye21#

当测试CompletableFuture时,您需要等到所有步骤都完成。
添加最终fut.join(),而不是Thread.sleep

sulc1iza

sulc1iza2#

JS测试的异步特性是一个使测试复杂化的问题(我们的大脑以同步的方式思考)。但是每个人(好吧,not everyone)都能接受它,因为这是NodeJS的特性,而不按照设计的方式使用这个工具可能是不明智的。
Java没有这个“问题”(你必须显式地选择使用NIO & Co来进行异步),这意味着你可以用正常(同步)的方式编写测试。因此,与其在不适合这种方式的环境中应用JS模式,不如用Java方式(或Rub-way,或.Net-way,或AlmostAnything-way)编写测试,而不用担心回调。
但是,如果您碰巧要测试异步代码(例如,您使用JMS之类的MOM),那么您可能需要查看Awaitility-用于测试此类情况的特殊库。

相关问题