How do I verify that code does not throw an exception in EK9?

← Error Handling and Exceptions · Ref: Q307

EK9 provides assertDoesNotThrow as a built-in keyword for verifying that an expression completes without throwing any exception. It is only valid inside @Test programs.

SYNTAX

assertDoesNotThrow(expression)
The test passes if the expression completes normally. The test fails if any exception is thrown.

USAGE

Use assertDoesNotThrow to verify no exception occurs:

  assertDoesNotThrow(safeFunction())

If safeFunction() throws, the test fails with structured diagnostic output.

FAILURE OUTPUT

When assertDoesNotThrow fails, EK9 provides structured output:

  assertDoesNotThrow FAILED
    Location: ./dev/tests.ek9:5:3
    Expression: riskyFunction()
    Expected: No exception
    Actual: org.ek9.lang::Exception
    Message: Division by zero

The output includes the exception type and message, captured at compile time from the AST.

WHEN TO USE

assertDoesNotThrow is valuable when:
- Testing boundary conditions that should not throw (edge cases).
- Verifying error recovery leaves the system in a stable state.
- Testing that previously throwing code has been fixed.
- Documenting in tests that certain operations are safe.

ASSERTTHROWS VS ASSERTDOESNOTTHROW

assertThrows(ExceptionType, expr): Verifies an exception IS thrown. Can capture the exception.
assertDoesNotThrow(expr): Verifies NO exception is thrown.
Both are compile-time restricted to @Test programs.

See Q306 for assertThrows. See Q305 for require vs assert vs throw. See Q156 for basic assertions. See Q209 for exception testing patterns.

Example

#!ek9
defines module qa.errorhandling.assertdoesnot

  defines function

    <?-
      A safe division that returns Result instead of throwing.
      Used to demonstrate safe operations.
    -?>
    safeDivide()
      ->
        a as Integer
        b as Integer
      <-
        rtn as Integer: 0

      if b == 0
        throw Exception("Division by zero")
      rtn: a / b

    <?-
      Safe string processing that never throws.
    -?>
    processName() as pure
      -> name as String
      <- rtn as String: `Hello, ${name}!`

  defines program

    @Test
    AssertDoesNotThrowStatementTest()
      stdout <- Stdout()

      stdout.println("=== assertDoesNotThrow as statement ===")

      assertDoesNotThrow(processName("EK9"))
      stdout.println("Verified: processName does not throw")

      assertDoesNotThrow(safeDivide(10, 2))
      stdout.println("Verified: safeDivide(10, 2) does not throw")

    @Test
    AssertDoesNotThrowMultipleTest()
      stdout <- Stdout()

      stdout.println("=== multiple assertDoesNotThrow checks ===")

      assertDoesNotThrow(processName("World"))
      stdout.println("Verified: processName(\"World\") is safe")

      assertDoesNotThrow(safeDivide(100, 5))
      stdout.println("Verified: safeDivide(100, 5) is safe")

      assertDoesNotThrow(safeDivide(0, 1))
      stdout.println("Verified: safeDivide(0, 1) is safe")

Common mistakes

E08091 — The parameter name is declared but never used in the function body. All parameters must be referenced. See ek9 -h E08091 for details.

Incorrect:

processName() as pure
      -> name as String
      <- rtn as String: "Hello!"

Correct:

processName() as pure
      -> name as String
      <- rtn as String: `Hello, ${name}!`
Other ways to ask this
  • How does assertDoesNotThrow work in EK9?
  • How do I test the happy path does not throw?
  • What is the EK9 equivalent of JUnit assertDoesNotThrow?

Coming from another language?

Java: JUnit assertDoesNotThrow(() -> code) wraps Executable. Python: no built-in equivalent, just run the code and let pytest catch unexpected exceptions. Rust: no equivalent, tests fail on panic by default. Go: no equivalent, tests fail on unrecovered panic. Kotlin: assertDoesNotThrow { code } from kotlin.test. EK9: assertDoesNotThrow(expression) is a built-in keyword, compile-time restricted to @Test programs, with structured failure output including exception type and message.

Keywords: assertDoesNotThrow, catch, diagnostic, exception, handle, happy path, no throw, safe, test, testing, verify