F # Observable - converting an event stream to a list

I was writing a unit test that checked for events emitted from a class. I followed the standard "IEvent <_>, Publish, Trigger inside a FSharp type template.

Can you recommend a "functional" way to achieve this?

Here are the options I can think of:

  • Convert an event stream to a list of strings and compare that list with the expected list
  • (not sure if there is a way) Convert the expected list to an event stream and compare the two streams.

Pointer to concise code will help a lot.

Thank!


Edit question 1: Answer to question:

This is what I have at the moment:

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)

      

The problems I feel are [a] using the reference cell [b], the observable .add essentially rewrites the reference for every event.

Is there a way to accomplish the same?

+3


source to share


1 answer


Events are associated with side effects , so he limits how hard he tries to try to be all Functional.

(Yes: you can build reactive systems in which immutable event data is passed through the system, filtered and aggregated along the way, but in the source that the event is raised is a side effect.)

Given that the unit test tests the block separately from its dependencies, verifying that events are raised correctly, uses an isolated "non-functional" part of the system, so I don't think you need to do this in a functional way.



Here's a simpler alternative:

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)

      

(This test function is just a normal function that returns bool

, but I'm sure you know how to convert it to a unit test.)

+3


source







All Articles