Question

I'm working on some code that follows a pattern of encapsulating all arguments to a method as a "request" object and returning a "response" object. However, this has produced some problems when it comes to mocking with MOQ. For example:

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; }
}

... in my test I want to stub the query to return the customer when the key is given

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});

Is what I want possible in MOQ?

Was it helpful?

Solution

What you are looking for it the It.Is<T> method where you can specify any matcher function (Func<T, bool>) for the argument.

For example checking for the key:

query.Setup(q => q.Execute(It.Is<QueryRequest>(q => q.Key == key)))
     .Returns(new QueryResponse {Customer = customer});

OTHER TIPS

I suspect you could do this with Custom Matchers.

From moq's QuickStart page:

// custom matchers
mock.Setup(foo => foo.Submit(IsLarge())).Throws<ArgumentException>();
...
public string IsLarge() 
{ 
  return Match.Create<string>(s => !String.IsNullOrEmpty(s) && s.Length > 100);
}

I suspect you could do a similar thing. Create a method that uses Match.Create<QueryRequest> to match your key, e.g.

public QueryRequest CorrectKey(string key)
{
    return Match.Create<QueryRequest>(qr => qr.Key == key);
}

and then

_query.Setup(q => q.Execute(CorrectKey(key))).Returns(new QueryResponse {Customer = customer});

Note: I haven't tried this code, so forgive me if it breaks entirely.

Oh, and for some mildly related self-promo: exactly this kind of complexity is what bugs me about Moq and other mocking tools. This is why I created a mocking library that allows you to check for method arguments with normal code: http://github.com/eteeselink/FakeThat. It's in the middle of a major refactoring (and renaming) process though, so you might want to hold your breath. Nevertheless, I'd be thrilled to hear what you think of it.

EDIT: Oh, @nemesv beat me to it, with a (probably) better answer. Ah well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top