How do I test that code throws or does not throw exceptions in EK9?
← Testing · Ref: Q209
EK9 provides try/catch for testing exception behavior, plus assertThrows and assertDoesNotThrow keywords for direct exception testing.
TRY/CATCH FOR EXCEPTION TESTING
Use try/catch to verify an exception is thrown:
try riskyFunction() assert false // Should not reach here catch -> ex as Exception assert ex? stdout.println("Caught: " + $ex)
ASSERTTHROWS
Verify that a block throws an exception:
assertThrows
riskyFunction()
The test passes only if an exception is thrown.
ASSERTDOESNOTTHROW
Verify that a block completes without throwing:
assertDoesNotThrow
safeFunction()
The test fails if any exception is thrown.
TESTING EXCEPTION MESSAGES
Catch and inspect exception details:
try throwError() catch -> ex as Exception assert $ex == "expected message"
See Q134 for try/catch basics. See Q136 for throwing exceptions. See Q156 for assertions.
See Q305 for require vs assert vs throw. See Q306 for assertThrows in depth. See Q307 for assertDoesNotThrow in depth.
Example
defines module qa.testdeep.exceptions defines function riskyDivide() as pure -> a as Integer b as Integer <- rtn as Integer? require b? rtn: a / b defines program ExceptionTestingDemo() stdout <- Stdout() // === TRY/CATCH FOR EXCEPTION TESTING === try result <- riskyDivide(10, 2) stdout.println(`10 / 2 = ${result}`) catch -> ex as Exception stdout.println("Unexpected error: " + $ex) // === TESTING ERROR CONDITIONS === try discarded <- riskyDivide(10, 0) stdout.println("Should not reach here " + $discarded) catch -> ex as Exception stdout.println("Caught expected error: " + $ex) // === ASSERTTHROWS / ASSERTDOESNOTTHROW === // In @Test programs: // assertThrows // riskyDivide(10, 0) // assertDoesNotThrow // riskyDivide(10, 2) stdout.println("assertThrows verifies exception is thrown") stdout.println("assertDoesNotThrow verifies no exception")
Common mistakes
E08091 — Both parameters a and b are declared but neither would be used in the function body if the implementation ignores them. All parameters must be referenced. See ek9 -h E08091 for details.
Incorrect:
riskyDivide() as pure -> a as Integer b as Integer <- rtn as Integer? rtn: 0
Correct:
riskyDivide() as pure -> a as Integer b as Integer <- rtn as Integer? require b? rtn: a / b
Other ways to ask this
- How do I verify exceptions in EK9 tests?
- How do assertThrows and assertDoesNotThrow work in EK9?
- How do I test error handling in EK9?
Coming from another language?
Java: JUnit assertThrows(() -> code) and assertDoesNotThrow(). Python: pytest.raises(ExceptionType). Rust: #[should_panic] attribute. Go: custom helper checking error returns. Kotlin: assertThrows<Exception> { code }. EK9: assertThrows/assertDoesNotThrow keywords, plus try/catch for detailed inspection.
Keywords: catch, coverage, assertDoesNotThrow, assertThrows, test, verify, error, exception, throw