11

我正在编写一些代码,这些代码遵循将方法的所有参数封装为“请求”对象并返回“响应”对象的模式。但是,这在使用 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});

我想要的最小起订量是可能的吗?

4

2 回答 2

21

您正在寻找的It.Is<T>方法是您可以为参数指定任何匹配器函数 ( Func<T, bool>) 的方法。

例如检查密钥:

query.Setup(q => q.Execute(It.Is<QueryRequest>(q => q.Key == key)))
     .Returns(new QueryResponse {Customer = customer});
于 2013-06-06T12:54:43.033 回答
0

我怀疑您可以使用自定义匹配器来做到这一点。

moq 的快速入门页面

// 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 以(可能)更好的答案击败了我。呃,好吧。

于 2013-06-06T12:55:50.493 回答