Asserting Errors in Unit Test when thrown in a choice

Given the following choice,

 choice SetAge: ()
      with
        age: Decimal
      controller owner
        do
          if age == 0 
          then error("Age cannot be 0") 
          else create this with age = age

I want to explicitly test in my UT (daml script) that the error, “Age cannot be 0”. How would i do that?

Or another way to frame my question is how do i get access to exceptions thrown by choices in Daml script so that i can do assertions upon them?

The Exception Handling section in Daml documentation discusses two options for handling exceptions: using Either data type and using try-catch block. For your use case you need to utilize both.
Here’s an example with a custom exception.

exception ZeroAge
  where
    message "Age cannot be zero"

template Student
  with
    age : Decimal
    name : Text
    school : Party
  where
    signatory school

    choice SetAge : ContractId Student
      with
        newage : Decimal
      controller school
      do
        if newage == 0.0
        then throw ZeroAge 
        else create this with age = newage

template TestHelper 
  with
    tester : Party
  where
    signatory tester

    nonconsuming choice Test_SetAge : Either Text Text
      with
        studentCid : ContractId Student
        newage : Decimal
      controller tester
      do
        try do
          exercise studentCid SetAge with newage
          return $ Right "Success"
        catch 
          (ex : ZeroAge) -> do
            return $ Left $ message ex

testSetAge = script do
  hs1 <- allocateParty "High School 1"
  alice_studentCid <- submit hs1 do
    createCmd Student with
      age = -1.0
      name = "Alice"
      school = hs1
  thCid <- submit hs1 do
    createCmd TestHelper with
      tester = hs1
  test_result <- submit hs1 do
    exerciseCmd thCid Test_SetAge with 
      studentCid = alice_studentCid
      newage = 0.0
  test_result === Left "Age cannot be zero"
  return ()

Note that, because exceptions are not propagated across submit, you cannot catch the exception thrown by SetAge choice in a try-catch block in Daml Script, and you need to utilize a helper template to catch the exception. For details on why this is the case and some additional examples check out previous discussions on the following threads

1 Like