如何使用f#判别联合类型作为TestCase属性参数?



我试图测试f#函数的返回结果是否匹配预期的区分联合情况。我使用NUnit来创建测试,它不喜欢区分联合类型作为TestCase参数。下面的测试用例无法编译:

[<TestCase("RF000123", Iccm.CallType.Request)>]
let ``callTypeFromCallNumber returns expected call type``
    callNumber callType =
    test <@ Iccm.callTypeFromCallNumber callNumber = callType @>

我希望这是NUnit的限制,但我不完全确定。我有一个想法来解决这个问题,我会张贴作为我的答案,但一个更优雅的解决方案会很好。

我如何使用一个区分的联合用例作为测试用例属性参数?

这不是NUnit的限制,而是f#语言(以及c#和VB)的限制:您只能将常量放入属性,而不是对象。区分联合在IL中编译为对象,因此不能将它们放入属性中。

可以将枚举放入属性中,因为它们是常量(在运行时是数字)。

从OP中的示例中,看起来CallType discriminationunion没有关联数据,因此您可以考虑将设计更改为enum:

type CallType =
    | Request = 0
    | Incident = 1
    | ChangeManagement = 2
    | Unknown = 3

你应该意识到,这使得CallType成为一个枚举;它不再是一个受歧视的工会。但是它应该允许您使用属性中的值。

这是我解决这个问题的方法。它工作得很好,尽管我发现它有点移位。我只是使用字符串代替类型,然后使用模式匹配将其转换为断言中的实际类型。

[<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 @>

最新更新