3
votes

I have a method with the following signature:

public string ParseFile<T>(string filepath, T model)

As you can see, the model is a generic type. The method is called from the tested code like this:

var model = new
        {
            SubmittedBy = submittedBy,
            SubmittedDateTime = DateTime.Now,
            Changes = changes
        };
string mailTemplate = provider.ParseFile(filePath, model);

I supply a mock object for the provider. I need to fake the call of this method, to return the value I provide, i.e. I need something like this:

_mockTemplateProvider.Setup(
            x => x.ParseFile(It.IsAny<string>(), It.IsAny<object>())).Returns("something");

When the test runs, the value I'm trying to set up is not returned. I can't use It.IsAny(), since the actual type is anonymous. If I try calling the method with an actual instance of object in debugger, it works. But how do I convince it to take an anonymous object? Or just don't care about arguments at all?

1
Can't reproduce (VS2015, Moq 4.2.1510.2205), the mock returns "something" as it was setup to do. Try creating an MVCE and see if you still see the problem. It's possible there's something else that's causing the issue here. - Patrick Quirk
Can reproduce with Moq 4.0.10827 in VS 2013. Gist here of my code: gist.github.com/thomaslangston/46734b4577d1d3eac8c9d2c331f9e278 - Thomas Langston

1 Answers

0
votes

The anonymous type is still an object, and the setup method you posted should be matched. Here is a working example

public interface IThing
{
    string DoIt<T>(T it);
}

public class Subject
{
    ...

    public string Execute()
    {
        var param = new
        {
            Foo = "bar",
            Baz = 23
        };
        return _thing.DoIt(param);
    }
}

[Test]
public void Test()
{
    var mockThing = new Mock<IThing>();
    mockThing.Setup(t => t.DoIt(It.IsAny<object>()))
        .Returns("expectedResult");

    var subject = new Subject(mockThing.Object);
    var result = subject.Execute();

    Assert.That(result, Is.EqualTo("expectedResult"));
}

You can also capture the object that is passed into the mock and perform assertions on it using a dynamic + the Callback method.

[Test]
public void Test()
{
    dynamic param = null;

    var mockThing = new Mock<IThing>();
    mockThing.Setup(t => t.DoIt(It.IsAny<object>()))
        .Callback<object>(p => param = p);

    var subject = new Subject(mockThing.Object);
    subject.Execute();

    Assert.That(param.Foo, Is.EqualTo("bar"));
    Assert.That(param.Baz, Is.EqualTo(23));
}