我想测试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<int>(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/