MUnit

MUnit

  • Docs
  • Blog
  • GitHub

›All Blog Posts

All Blog Posts

  • Publish Scala 2 and Scala 3 macros together
  • Using ScalaCheck with MUnit
  • Cross-platform async testing support
  • MUnit is a new Scala testing library

Cross-platform async testing support

February 16, 2020

Ólafur Páll Geirsson

Ólafur Páll Geirsson

MUnit v0.4.x did not support truly async tests on platforms like JavaScript. For example, the following test case would succeed even if it returns a failing future:

test("should fail after 100 milliseconds") {
  val p = Promise[Unit]()
  setTimeout(100) {
    p.failure(new RuntimeException("boom"))
  }
  p.future
}

The latest MUnit v0.5.0 release fixes this issue by adding support for async tests on all platforms meaning that the example test case above fails as expected after 100 milliseconds.

Breaking changes

If you did not override any munit* methods then you should be able to upgrade to v0.5.0 easily. Most commonly used methods like test("name") { ... } are unchanged in this release.

The breaking changes in this release mostly involve replacing Any with Future[Any].

-- MUnit v0.4.x
++ MUnit v0.5.x

-  def munitTestValue(body: Any): Any
+  def munitTestValue(body: => Any): Future[Any]

-  def munitRunTest(options: TestOptions, body: Any): Any
+  def munitRunTest(options: TestOptions, body: () => Future[Any]): Future[Any]

-  def munitExpectFailure(options: TestOptions, body: Any): Any
+  def munitExpectFailure(options: TestOptions, body: () => Future[Any]): Future[Any]

-  def munitFlaky(options: TestOptions, body: Any): Any
+  def munitFlaky(options: TestOptions, body: () => Future[Any]): Future[Any]

To give an example how to migrate from the old API to the new API. The docs demonstrated how to automatically start evaluating a lazy future called Task by overriding munitTestValue. The old override looked like this:

override def munitTestValue(testValue: Any): Any =
  testValue match {
    case Task(run) => Await.result(run(), munitTimeout)
    case _ => super.munitTestValue(testValue)
  }

The override with the new signature now looks like this instead:

override def munitTestValue(testValue: => Any): Future[Any] =
  super.munitTestValue(testValue).flatMap {
    case LazyFuture(run) => run()
    case value => Future.successful(value)
  }
Recent Posts
  • Breaking changes
MUnit
Overview
Getting started
Social
Copyright © 2023 Scalameta