Mar*_*son 8 f# discriminated-union fsunit
我想检查一个值是否是受歧视联合的特定情况,而不必检查任何包含的数据.我的动机是每个单元测试只测试一件事.
示例如下(最后两行给出编译错误):
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
Run Code Online (Sandbox Code Playgroud)
这可以在FsUnit中完成吗?
我知道这个答案,但我不想为每个案例编写匹配的函数(在我的实际代码中,有两个以上).
如果你不介意使用反射,这个答案的isUnionCase功能可以很方便:
increment state
|> isUnionCase <@ StateTwo @>
|> should equal true
Run Code Online (Sandbox Code Playgroud)
请注意,它有点冗长,因为在比较值之前需要调用函数.
一个类似但更轻的方法可以比较标签:
// 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"
Run Code Online (Sandbox Code Playgroud)
请注意,这不是类型安全的,您可以轻松拼错工会案例名称.
我要做的是创建一个类似的DU用于比较目的:
type MyStateCase =
| StateOneCase
| StateTwoCase
let categorize = function
| StateOne _ -> StateOneCase
| StateTwo _ -> StateTwoCase
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以定义categorize一次并多次使用它.
increment state
|> categorize
|> should equal StateTwoCase
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1833 次 |
| 最近记录: |