我正在尝试使用Foq来测试与Foq的接口。
到目前为止,我看到的所有示例都是相对简单的,如下所示:
let users = [|{ID = 1; pass = true};{ID = 2; pass= false}|]
type IFoo =
abstract member Bar: int -> bool
//tests with Foq
let dataAccess =
Mock<IFoo>()
.Setup(fun x-> <@ x.Bar(users.[0].ID) @>).Returns(users.[0].pass)
.Setup(fun x-> <@ x.Bar(users.[1].ID) @>).Returns(users.[1].pass)
.Create()这些例子来源于“Testing with F# - Mikael Lundin”。
我也通过谷歌搜索进行了研究(这个链接很有帮助- http://trelford.com/blog/post/Foq.aspx)
然而,我想要测试的真实接口如下:
type IParameters =
abstract member ParameterDate : int->string->DateTime
type IDataSource =
abstract member MortParameters: IParameters我尝试了许多不同的方法来测试它们(例如,定义一个签名为int->string的函数作为设置的输入。或者,将返回值作为字符串->DateTime,并将设置作为整数。
我的问题实际上是这样的:当使用Foq测试接口时,我如何将测试扩展到具有任何通用长度的函数签名的接口(例如a->b->c->d->e等)。
发布于 2016-05-09 18:04:43
由于ParameterDate是一个具有函数类型的属性,因此您可以将其设置为返回lambda值的属性。请参阅property set-up in Foq的示例。对于您的案例,这应该很容易修改:
let instance =
Mock<System.Collections.IList>()
.Setup(fun x -> <@ x.Count @>).Returns(1)
.Create()然而,我猜你会失去在函数输入上有固定期望的严格模拟的能力。
要仅强制由mock属性返回的函数的预期输入,您可以提供如下函数:
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Invalid mock input"我可能会到此为止,但如果您正在处理需要验证函数是否被调用的代码,而不仅仅是确保您获得正确的输出,您可以添加一个助手,如下所示:
type Verifiable<'a, 'b> (f : 'a -> 'b) =
let called = ref false
member this.Func x =
called := true
f x
member this.Verify() =
if not called.Value then failwith "Mock function was not called"下面是你将如何使用它:
let parameterDateMock =
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Unexpected mock input"
|> Verifiable
let parameters =
{ new IParameters with member this.ParameterDate i s = parameterDateMock.Func i s }
parameters.ParameterDate 1 ""
parameterDateMock.Verify()注意:这只能验证函数是用至少一个参数调用的。它可能通过currying返回了另一个函数,但实际上并没有运行模拟函数体中的代码。要解决这个问题,您需要为每个函数指定一个可验证类的变体,并在每种情况下使用正确的类。
https://stackoverflow.com/questions/37100594
复制相似问题