我正在编写一个单元测试来验证从类中触发的事件。我遵循标准的“IEvent<_>, Publish, Trigger inside a FSharp type”模式。
你能推荐实现这一目标的“功能性”方式吗?
以下是我能想到的选项:
指向被剪断的代码的指针将有很大帮助。
谢谢!
编辑 1:回答马克的问题:
这是我目前所拥有的:
let expectedFiles = [ "c:\a\1"
"c:\a\2" ]
[<Fact>]
let ``Can find files from a folder`` () =
let ad = new FileSearchAdapter()
let foundFiles = ref []
ad.FileFound
|> Observable.scan (fun acc e -> e::acc) []
|> Observable.add (fun acc -> foundFiles := acc)
ad.FindFiles @"c:\a"
Assert.Equal<string list>(expectedFiles, !foundFiles)
我觉得这里的问题是 [a] 使用引用单元格 [b] observable.add 基本上覆盖了每个事件的引用。
有没有实现相同功能的方法?
最佳答案
事件都是关于副作用的 ,因此尝试使其成为 Functional 的意义是有限的。
(是的:您可以构建响应式系统,其中不可变的事件数据流经系统,在此过程中被过滤和聚合,但在源头上,引发事件是一种副作用。)
鉴于单元测试是在独立于其依赖项的情况下测试单元,测试事件是否正确引发,练习系统中孤立的、“无功能”的部分,所以我认为您不必以功能方式进行.
这是一个更简单的替代方案:
open System.Collections.Generic
let ``Can find files from a folder`` () =
let ad = new FileSearchAdapter()
let foundFiles = List<string>()
ad.FileFound.Add(fun (sender, args) -> foundFiles.Add args)
ad.FindFiles "c:\a"
let expectedFiles = [ "c:\a\1"; "c:\a\2" ]
expectedFiles = (foundFiles |> Seq.toList)
(这个测试函数只是一个返回
bool
的普通函数,但我相信你知道如何将它转换为单元测试。)
关于F# Observable - 将事件流转换为列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30271980/