我试图在F#中测试一个MailboxProcessor.我想测试我发布的函数f实际上是在发布消息时执行的.
原始代码使用的是Xunit,但我创建了一个fsx,我可以使用fsharpi执行它.
到目前为止我这样做:
open System open FSharp open System.Threading open System.Threading.Tasks module MyModule = type Agent<'a> = MailboxProcessor<'a> let waitingFor timeOut (v:'a)= let cts = new CancellationTokenSource(timeOut|> int) let tcs = new TaskCompletionSource<'a>() cts.Token.Register(fun (_) -> tcs.SetCanceled()) |> ignore tcs ,Async.AwaitTask tcs.Task type MyProcessor<'a>(f:'a->unit) = let agent = Agent<'a>.Start(fun inbox -> let rec loop() = async { let! msg = inbox.Receive() // some more complex should be used here f msg return! loop() } loop() ) member this.Post(msg:'a) = agent.Post msg open MyModule let myTest = async { let (tcs,waitingFor) = waitingFor 5000 0 let doThatWhenMessagepostedWithinAgent msg = tcs.SetResult(msg) let p = new MyProcessor(doThatWhenMessagepostedWithinAgent) p.Post 3 let! result = waitingFor return result } myTest |> Async.RunSynchronously |> System.Console.WriteLine //display 3 as expected
这段代码有效,但对我来说看起来并不好.
1)在f#中是否正常使用TaskCompletionSource,还是有一些专门的东西可以让我等待完成?
2)我在waitingFor函数中使用第二个参数来约束它,我知道我可以使用类型MyType <'a>()来做它,还有另一种选择吗?我宁愿不使用我觉得麻烦的新MyType.
3)有没有其他选择来测试我的代理而不是这样做?到目前为止我发现的关于这个主题的唯一帖子是2009年的这篇博文http://www.markhneedham.com/blog/2009/05/30/f-testing-asynchronous-calls-to-mailboxprocessor/