How to assert an exception is expected
Asked Answered
C

1

5

I'm on a Mac running F# using .NET Core 2.0.

I have a function that looks like this:

let rec evaluate(x: string) =
  match x with
  // ... cases
  | _ -> failwith "illogical"

I'd like to write an Expecto test that validates that the exception is thrown as expected, something along the lines of:

// doesn't compile
testCase "non-logic" <| fun _ ->
  Expect.throws (evaluate "Kirkspeak") "illogical" 

The error is

This expression was expected to have type 'unit -> unit' but here has type 'char'

unit -> unit makes me this is analogous to Assert.Fail, which is not what I want.

Being somewhat new to F# and Expecto, I'm having trouble locating a working example of asserting that an exception is thrown as expected. Does anyone have one?

Chill answered 11/6, 2018 at 20:11 Comment(0)
C
7

Expect.throws has the signature (unit -> unit) -> string -> unit so the function you want to test must be (unit -> unit) or be wrapped inside a function that is (unit -> unit).

let rec evaluate (x: string) : char =
  match x with
  // ... cases
  | _ -> failwith "illogical"

The compiler error is telling you that the function you passed to Expect.throws does not have the right signature yet.

[<Tests>]
let tests = testList "samples" [
    test "non-logic" {
      // (evaluate "Kirkspeak") is (string -> char)
      // but expecto wants (unit -> unit)
      Expect.throws (evaluate "Kirkspeak") "illogical"
    }
]

[<EntryPoint>]
let main argv =
    Tests.runTestsInAssembly defaultConfig argv

One way to make it work is to change

Expect.throws (evaluate "Kirkspeak") "illogical"

to

// you could instead do (fun () -> ...)
// but one use of _ as a parameter is for when you don't care about the argument
// the compiler will infer _ to be unit
Expect.throws (fun _ -> evaluate "Kirkspeak" |> ignore) "illogical"

Now expecto is happy!

expecto says the test asserting an exception throws passes

This answer was the way I thought through it. It is usually helpful to follow the type signatures.

EDIT: I saw your error message saying This expression was expected to have type 'unit -> unit' but here has type 'char' so I updated my answer to match it.

Composed answered 11/6, 2018 at 21:54 Comment(6)
Thank you, this answer is headed in the right direction! However, when I run this code, the exception isn't caught. Are you running this against .NET Framework or .NET Core? (I'm on a Mac.)Chill
That's strange. I pulled all the code I put in the answer from a netcoreapp2.0 console project. Are you getting some kind of further message?Composed
Yes, Exception has occurred: CLR/System.Exception An exception of type 'System.Exception' occurred in tests.dll but was not handled in user code: 'illogical' at [email protected](Unit _arg1) in /Users/.../tests/Tests.fs:line 121 at Expecto.Expect.throws(FSharpFunc`2 f, String message)Chill
Is it possible to share the test code project in a github gist or something? I think this sounds like some syntax issue now. Otherwise I am not sure how I can help further.Composed
If it helps, here is my source github.com/gfritz/fsharp-stack. dotnet run should result in my screenshot.Composed
I had a moment to download it, and it's having trouble finding FSharp.Core 4.5. I don't have time to troubleshoot today, but let's assume it's a local setup issue for the moment.Chill

© 2022 - 2024 — McMap. All rights reserved.