I am trying to test that the return result from an F# function matches an expected discriminated union case. I am using NUnit to create the tests and it does not like the discriminated union type as a TestCase
parameter. The following test case fails to compile:
[<TestCase("RF000123", Iccm.CallType.Request)>]
let ``callTypeFromCallNumber returns expected call type``
callNumber callType =
test <@ Iccm.callTypeFromCallNumber callNumber = callType @>
I expect that this is a limitation of NUnit but I am not completely sure. I have an idea to work around this which I will post as my answer but a more elegant solution will be nice.
How can I use a discriminated union case as a test case attribute parameter?
It's normal for kids to swear at one time or another. Young kids will often repeat something they've heard. Older kids often want to test their parents' reactions. If your child has started using a few choice words, there are several discipline techniques you can use to curb their use of inappropriate language.
It has absolutely no age limit. Ages two and three, you start cursing. Most people begin working around 10 to 14. From 14 to 16, teenagers would most likely swear in front of their parents.
This isn't a limitation of NUnit, but of the F# language (as well as C# and VB): You can only put constants into attributes, but not objects. Discriminated Unions compile to objects in IL, so you can't put them into attributes.
You can put enums into attributes, though, since they're constants (they're numbers at run-time).
From the example in the OP, it looks like the CallType
Discriminated Union has no associated data, so you could consider changing the design to an enum instead:
type CallType =
| Request = 0
| Incident = 1
| ChangeManagement = 2
| Unknown = 3
You should realise, though, that that makes CallType
an enum; it's no longer a Discriminated Union. It should enable you to use the values in attributes, though.
Here is my workaround to the problem. It works just fine although I find it a little bit make shift. I just use strings in place of the types and then pattern match to convert to the actual type in the assertion.
[<TestCase("RF000123", "Request")>]
[<TestCase("IM000123", "Incident")>]
[<TestCase("CM000123", "ChangeManagement")>]
[<TestCase("AR000123", "Unknown")>]
let ``callTypeFromCallNumber returns expected call type``
callNumber callType =
test <@ Iccm.callTypeFromCallNumber callNumber = match callType with
| "Request" -> Iccm.CallType.Request
| "Incident" -> Iccm.CallType.Incident
| "ChangeManagement" -> Iccm.CallType.ChangeManagement
| _ -> Iccm.CallType.Unknown @>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With