我正在研究一些代码,这些代码遵循将方法的所有参数封装为“请求”对象并返回“响应”对象的模式。但是,在使用MOQ进行模拟时,这会产生一些问题。例如:
public class Query : IQuery
{
public QueryResponse Execute(QueryRequest request)
{
// get the customer...
return new QueryResponse { Customer = customer };
}
}
public class QueryRequest
{
public string Key { get; set; }
}
public class QueryResponse
{
public Customer Customer { get; set; }
}
...在我的测试中,我希望将查询存根,以便在给出密钥时返回客户
var customer = new Customer();
var key = "something";
var query = new Mock<ICustomerQuery>();
// I want to do something like this (but this does not work)
// i.e. I dont care what the request object that get passed is in but it must have the key value I want to give it
query.Setup(q => q.Execute(It.IsAny<QueryRequest>().Key = key)).Returns(new QueryResponse {Customer = customer});
MOQ中我想要的是什么?
答案 0 :(得分:11)
您正在寻找It.Is<T>
方法,您可以为参数指定任何匹配器函数(Func<T, bool>
)。
例如检查密钥:
query.Setup(q => q.Execute(It.Is<QueryRequest>(q => q.Key == key)))
.Returns(new QueryResponse {Customer = customer});
答案 1 :(得分:0)
我怀疑你可以使用Custom Matchers做到这一点。
// custom matchers
mock.Setup(foo => foo.Submit(IsLarge())).Throws<ArgumentException>();
...
public string IsLarge()
{
return Match.Create<string>(s => !String.IsNullOrEmpty(s) && s.Length > 100);
}
我怀疑你可以做类似的事情。创建一个使用Match.Create<QueryRequest>
匹配您的密钥的方法,例如
public QueryRequest CorrectKey(string key)
{
return Match.Create<QueryRequest>(qr => qr.Key == key);
}
然后
_query.Setup(q => q.Execute(CorrectKey(key))).Returns(new QueryResponse {Customer = customer});
注意:我没有尝试过这段代码,如果完全破坏,请原谅我。
哦,对于一些温和相关的自我宣传:正是这种复杂性让我对Moq和其他嘲弄工具感到困惑。这就是为什么我创建了一个模拟库,允许您使用普通代码检查方法参数:http://github.com/eteeselink/FakeThat。它正处于重大重构(和重命名)过程的中间,所以你可能想屏住呼吸。不过,我很高兴听到你的想法。
编辑:哦,@ nemesv用一个(可能)更好的答案打败了我。好吧。