[英]Testing interfaces with foq
I am trying to use Foq to testing an interface with Foq. 我正在尝试使用Foq来测试与Foq的接口。
So far, all examples I have seen for this have been relatively simple, such as the following: 到目前为止,我所看到的所有示例都相对简单,如下所示:
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()
The examples have been sourced from 'Testing with F# - Mikael Lundin' 这些例子来自'用F#测试 - Mikael Lundin'
I have also researched this through a bit of googling (this link was helpful - http://trelford.com/blog/post/Foq.aspx ) 我也通过一些谷歌搜索研究了这个(这个链接很有用 - http://trelford.com/blog/post/Foq.aspx )
However, the real Interfaces I want to test are the following: 但是,我要测试的真实接口如下:
type IParameters =
abstract member ParameterDate : int->string->DateTime
type IDataSource =
abstract member MortParameters: IParameters
I have tried a number of different ways to test these (eg defining a function with a signature of int->string to be used as the input to the setup. Alternatively, having the return value as a string->DateTime and the Setup as just an integer. 我已经尝试了许多不同的方法来测试这些(例如,使用int-> string的签名定义一个函数作为设置的输入。或者,将返回值作为字符串 - > DateTime并将Setup设置为只是一个整数。
My question is really the following: When testing interfaces using Foq, how can I extend the testing to interfaces with function signatures of any general length (eg a->b->c->d->e etc.) 我的问题实际上如下:当使用Foq测试接口时,如何将测试扩展到具有任何常规长度的功能签名的接口(例如a-> b-> c-> d-> e等)
Since ParameterDate
a property with a function type, you could just set it up as a property that returns a lambda value. 由于
ParameterDate
是一个具有函数类型的属性,因此您可以将其设置为返回lambda值的属性。 See an example of property set-up in Foq . 请参阅Foq中的属性设置示例 。 This should be easy to modify for your case:
这应该很容易修改为您的情况:
let instance =
Mock<System.Collections.IList>()
.Setup(fun x -> <@ x.Count @>).Returns(1)
.Create()
However, I guess you would lose the ability to have a strict mock with fixed expectations on the function inputs. 但是,我猜你会失去对函数输入进行严格模拟和固定期望的能力。
To enforce only expected inputs for the function returned by the mock property you could provide a function like this: 要仅对mock属性返回的函数强制执行预期输入,您可以提供如下函数:
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Invalid mock input"
I would probably stop here, but if you're working with code where you need to verify a function was called, as opposed to just ensuring you get the correct output, you could add a helper like this: 我可能会在这里停下来,但是如果你正在使用需要验证函数被调用的代码,而不是只是确保你得到正确的输出,你可以添加一个这样的帮助:
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"
And here's how you would use it: 以下是您将如何使用它:
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()
Caveat: This only verifies the function was called with at least one parameter. 警告:这只验证使用至少一个参数调用函数。 It may have returned another function by currying and not actually run the code in the mock function body.
它可能通过currying返回另一个函数,而不是实际运行mock函数体中的代码。 To get around that you'd need a variation of the Verifiable class for every function arity and use the right one in each case.
为了解决这个问题,你需要为每个函数arity更改Verifiable类,并在每种情况下使用正确的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.