F# Observable - 将事件流转换为列表

标签 f# functional-programming reactive-programming observable

我正在编写一个单元测试来验证从类中触发的事件。我遵循标准的“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/

    相关文章:

    F# 向上舍入到特定的小数位数

    javascript - 这个循环的函数式替换是什么?

    java - 使用 RxJava 生成无限自然数序列

    java - 是否可以根据某些过滤器将内容从一个通量插入到另一个通量中

    f# - 为什么计算表达式不跨越finally block

    f# - Csv 类型提供程序转换为 Json

    f# - 这是用于相当快速的无限递归序列的惯用 F# 吗?

    scala - 标量代码作为数据

    java - 如何创建一个新列表并在单个语句中添加一个值

    javascript - 如果我使用相同的对象,为什么我的 console.log 显示不同的属性值? react js