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() stdout.println("Should not reach here") catch -> ex as Exception stdout.println("Caught: " + $ex)
The callee must THROW explicitly. Integer division by zero does not throw - it returns an unset Integer - and a failed 'require' is a Panic that no catch block sees. So guard and throw:
if b == 0 throw Exception("division by zero")
ASSERTTHROWS
Verify that an expression throws an exception of a given type:
assertThrows(Exception, riskyFunction())
The test passes only if an exception is thrown.
ASSERTDOESNOTTHROW
Verify that an expression 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? if b == 0 throw Exception("division by zero") 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 === // riskyDivide throws explicitly: dividing by zero alone would // give an unset Integer, not an exception 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(Exception, riskyDivide(10, 0)) // assertDoesNotThrow(riskyDivide(10, 2)) stdout.println("assertThrows verifies exception is thrown") stdout.println("assertDoesNotThrow verifies no exception")
Common mistakes
E08091 — Parameters a and b are declared but a body that ignores them (a stub returning 0) never references them. Every parameter must be used. See ek9 -h E08091 for details.
Incorrect:
rtn: 0
Correct:
require b? if b == 0 throw Exception("division by zero") 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(Type, expr) / assertDoesNotThrow(expr) keywords, plus try/catch for detailed inspection. Integer division by zero gives an unset result rather than throwing, so throw explicitly.
Keywords: error, verify, test, assertThrows, assertDoesNotThrow, coverage, catch, throw, exception