Макет `printfn` в тестах F#
Я пытаюсь написать тест для небольшой библиотеки. Я пишу, что (по сути) просто регистрируется в консоли.
Есть ли способ смоделировать функцию, как это F#?
пример: в src/Lib/Lib.fs
module Lib
let print msg = printfn "Your message is: %s" msg
затем в тесте /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"
Примечание: я знаю, что в настоящее время print
возвращается unit
- Я ищу способ сделать утверждения о том, что передается printfn
(или, в идеале, то, что отправляется на стандартный вывод, который меньше зависит от реализации).
Я пытался напрямую назначить фиктивную функцию Printf.printfn
безрезультатно (очевидно, когда я об этом думаю). Возможно ли захватить вывод на консоль? Или высмеивать printfn
функция (это детали реализации, но я могу жить с этим).
1 ответ
Вот что я использую для тестирования:
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
Код, который я тестирую звонки printoutfn
или же printoutfns
которая является тихой версией.
Чтобы проверить вывод, я делаю это так:
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"
Обратите внимание, как он включает символ новой строки: \n
,
Есть два вызова: StdOut.call func param
а также StdOut.run func param
первый возвращает значение функции и вывод, второй возвращает только вывод