I'm trying to use FsUnit (under the hood it uses NUnit) to test my F# code, but it's having trouble handling generic discriminated unions. I understand why it happens, but I'm trying to find a way to write tests without annotating my expected values. Any advice? Are there maybe frameworks better suited for this?
type OptionWithReason<'a> =
| Some of 'a
| None of string
let reason = "division by 0 is not yet supported"
let safeDivide x y =
if y = 0 then
None reason
else
Some(x/y)
let result = safeDivide 1 0
let expected = None reason
let expectedExplicit: int OptionWithReason = None reason
let test1 = result = expected //true
let test2 = result = expectedExplicit //true
NUnit.Framework.Assert.AreEqual(expectedExplicit,result) //pass
NUnit.Framework.Assert.AreEqual(expected,result) //fail :(
A part of the problem in your code is that Assert.AreEqual
takes two parameters as obj
and so the compiler does not know that the types should be the same - if it knows this, then it would infer that expected
is of type int OptionWithReason
(to match with result
).
An easy way to fix this is to define a helper function for areEqual
that takes parameters of the same type:
let areEqual (first:'T) (second:'T) =
NUnit.Framework.Assert.AreEqual(first, second)
Now you can write your assertion as:
areEqual expected result
The compiler will infer that the types of expected
and result
are the same and it should work.