daazc
daazc

Reputation: 23

For unit tests written in F# with mstest in vs2012, how do I assert that an exception is raised?

I'm writing unit tests in F# using MSTest, and I'd like to write tests that assert that an exception is raised. The two methods that I can find for doing this are either (1) write the tests in C# or (2) don't use MSTest, or add another test package, like xunit, on top of it. Neither of these is an option for me. The only thing I can find on this is in the MSDN docs, but that omits F# examples.

Using F# and MSTest, how do I assert that a particular call raises a particular exception?

Upvotes: 2

Views: 626

Answers (2)

Mike Zboray
Mike Zboray

Reputation: 40818

MSTest has an ExpectedExceptionAttribute that can be used, but it is a less than ideal way to test an exception has been thrown because it doesn't let you assert the specific call that should throw. If any method in the test method throws the expected exception type, then the test passes. This can be bad with commonly used exception types like InvalidOperationException. I use MSTest a lot and we have a Throws helper method for this in our own AssertHelper class (in C#). F# will let you put it into an Assert module so that it appears with all the other Assert methods in intellisense, which is pretty cool:

namespace FSharpTestSpike

open System
open Microsoft.VisualStudio.TestTools.UnitTesting

module Assert =

  let Throws<'a> f =
    let mutable wasThrown = false
    try
      f()
    with
    | ex -> Assert.AreEqual(ex.GetType(), typedefof<'a>, (sprintf "Actual Exception: %A" ex)); wasThrown <- true

    Assert.IsTrue(wasThrown, "No exception thrown")

[<TestClass>]
type MyTestClass() =     

  [<TestMethod>]
  member this.``Expects an exception and thrown``() =
    Assert.Throws<InvalidOperationException> (fun () -> InvalidOperationException() |> raise)

  [<TestMethod>]
  member this.``Expects an exception and not thrown``() =
    Assert.Throws<InvalidOperationException> (fun () -> ())

  [<TestMethod>]
  member this.``Expects an InvalidOperationException and a different one is thrown``() =
    Assert.Throws<InvalidOperationException> (fun () -> Exception("BOOM!") |> raise)

Upvotes: 2

Nikon the Third
Nikon the Third

Reputation: 2831

Like this?

namespace Tests

open Microsoft.VisualStudio.TestTools.UnitTesting
open System

[<TestClass>]
type SomeTests () =

    [<TestMethod; ExpectedException (typeof<InvalidOperationException>)>]
    member this.``Test that expects InvalidOperationException`` () =
        InvalidOperationException () |> raise |> ignore

Upvotes: 1

Related Questions