我想检查一个值是否属于已区分联合的特殊情况,而不必检查任何包含的数据。我的动机是每次单元测试只能测试一件事。
示例如下(最后两行给出了编译错误):
module MyState
open NUnit.Framework
open FsUnit
type MyState =
| StateOne of int
| StateTwo of int
let increment state =
match state with
| StateOne n when n = 10 -> StateTwo 0
| StateOne n -> StateOne (n + 1)
| StateTwo n -> StateTwo (n + 1)
[<Test>]
let ``incrementing StateOne 10 produces a StateTwo`` ()=
let state = StateOne 10
(increment state) |> should equal (StateTwo 0) // works fine
(increment state) |> should equal (StateTwo _) // I would like to write this...
(increment state) |> should be instanceOfType<StateTwo> // ...or this
可以在FsUnit中完成吗?
我知道this answer,但不希望不必为每种情况编写匹配函数(在我的真实代码中,远远超过两个)。
最佳答案
如果您不介意使用反射,那么this answer中的isUnionCase
函数可能会很方便:
increment state
|> isUnionCase <@ StateTwo @>
|> should equal true
请注意,这有点冗长,因为在比较值之前需要进行函数调用。
一种类似但更轻松的方法是比较标签:
// Copy from https://stackoverflow.com/a/3365084
let getTag (a:'a) =
let (uc,_) = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(a, typeof<'a>)
uc.Name
increment state
|> getTag
|> should equal "StateTwo"
请注意,这不是类型安全的,并且您很容易会误拼出联合用例名称。
我要做的是创建一个类似的DU进行比较:
type MyStateCase =
| StateOneCase
| StateTwoCase
let categorize = function
| StateOne _ -> StateOneCase
| StateTwo _ -> StateTwoCase
这样,您一次定义了
categorize
并多次使用。increment state
|> categorize
|> should equal StateTwoCase
关于f# - 如何使用FsUnit检查歧视工会的情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19001567/