简体   繁体   English

在F#测试中模拟`printfn`

[英]Mock `printfn` in F# tests

I'm trying to write a test for a small lib I'm writing that (essentially) just logs to the console. 我正在尝试为一个小的lib写一个测试(实际上)只是记录到控制台。

Is there a way to mock function like this is F#? 有没有办法像F#这样模拟函数?

example: in src/Lib/Lib.fs 示例:在src / Lib / Lib.fs中

module Lib

let print msg = printfn "Your message is: %s" msg

then, in test/LibTest/Lib.fs 然后,在test / LibTest / Lib.fs中

module LibTest

open NUnit.Framework
open FsUnit

[<Test>]
let ``should print what I expect``() =
  print "test" |> should equal "Your message is: test"

Note: I'm aware that currently print returns unit - I am looking for a way to make assertions about what is passed to printfn (or, more ideally, what is sent to stdout, which relies less on implementation). 注意:我知道当前的print返回unit -我正在寻找一种方法来断言传递给printfn (或更理想的情况是,发送给stdout的内容,它对实现的printfn较小)。

I've tried directly assigning a mock function to Printf.printfn to no avail (obviously, when I think about it). 我试图直接将模拟函数分配给Printf.printfn (显然,当我考虑时)。 Is it possible to capture the output to the console? 是否可以将输出捕获到控制台? Or to mock the printfn function (it's an implementation detail, but I can live with that). 或模拟printfn函数(这是一个实现细节,但我可以接受)。

This is what I use for testing: 这是我用于测试的内容:

module StdOut =
    let stdout = System.Text.StringBuilder()
    let out (s:string) = stdout.Append s |> ignore
    let call func parm =
        stdout.Clear() |> ignore
        func parm, stdout.ToString()
    let run f p = call f p |> snd

let inline  (|>!) v f   = f v ; v
/// used to capture print outs for testing. like printfn
let printoutfn  fmt = fmt |> Printf.ksprintf (fun s -> s + "\n" |>! printf "%s"|> StdOut.out)
/// silent version of printoutfn
let printoutfns fmt = fmt |> Printf.ksprintf (fun s -> s + "\n"                |> StdOut.out)
let printout      v = printoutfn "%A" v

The code I am testing calls printoutfn or printoutfns which is the silent version. 我正在测试的代码称为printoutfnprintoutfns ,这是静默版本。

To test the output I do it like this: 为了测试输出,我这样做:

let print msg = printoutfn "Your message is: %s" msg

[<Test>] 
let ``should print what I expect``() =
      StdOut.run print "test" |> should equal "Your message is: test\n"

Notice how it includes the newline character: \\n . 注意它如何包含换行符: \\n

There are two invocations: StdOut.call func param and StdOut.run func param the former returns the function value and the output, the latter only returns the output 有两个调用: StdOut.call func paramStdOut.run func param前者返回函数值和输出,后者仅返回输出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM