Daws
Daws

Reputation: 702

How does one trigger and test events on an IObservable?

I'm writing a basic UDP Server that listens for messages on a given port, massages the input a little, and triggers an event with the processed message. I would like to write tests that send a message to the server and verify that the correct event is raised.

The server looks something like this:

type UdpServer() =
    let messageReady = new Event<string>()

    member x.Start () = async {
            let rec loop () =                 
                let message = receiveMessage ()
                messageReceived.Trigger(message)
                return loop ()
            return! loop ()
        }

    member x.MessageReady = messageReady.Publish

I'd like to write a test something like this:

[<Test>]
let ``Should process message correctly`` () =
    let server = new UdpServer()
    server.Start() |> Async.Start
    sendMessageToServer "test message"

    // This will wait indefinitely since the message was already sent in the previous line
    let processedMessage = server.MessageReady |> Async.AwaitEvent |> Async.RunSynchronously
    processedMessage |> should be "expected output"

How do I send a message to the server and then test that the MessageReady event was triggered correctly? I could use a mutable to store the value, but this doesn't seem like the F# way:

let mutable processedMessage = ""
server.MessageReady |> Observable.subscribe(fun m -> processedMessage <- m)
sendMessageToServer "test message"
processedMessage |> should be "expected output"

Upvotes: 2

Views: 114

Answers (1)

Vasily Kirichenko
Vasily Kirichenko

Reputation: 671

Consuming observables and events are inherently imperative, so it's ok to use mutables/ref cells to check whether they are raised.

Upvotes: 1

Related Questions