How to mock a method call that takes a dynamic object

喜欢而已 提交于 2019-11-30 23:05:37

问题


Say I have the following:

public interface ISession 
{
   T Get<T>(dynamic filter); }
}

And I have the following code that I want to test:

var user1 = session.Get<User>(new {Name = "test 1"});
var user2 = session.Get<User>(new {Name = "test 2"});

How would I mock this call?

Using Moq, I tired doing this:

var sessionMock = new Mock<ISession>();
sessionMock.Setup(x => x.Get<User>(new {Name = "test 1")).Returns(new User{Id = 1});
sessionMock.Setup(x => x.Get<User>(new {Name = "test 1")).Returns(new User{Id = 2});

And that didn't work. The returned results is null

I also tried to do the following with Rhino Mocks:

var session = MockRepository.GenerateStub<ISession>();
session.Stub(x => x.Get<User>(new {Name = "test 1"})).Return(new User{Id=1});

No luck either. Null again.

So how would I do this?

Thanks,


回答1:


You can use the It.Is<object> matcher together with reflection. You cannot use dynamic in expression trees so It.Is<dynamic> won't work that's why you need reflection to get the your property value by name:

sessionMock
    .Setup(x => x.Get<User>(
        It.Is<object>(d => d.GetPropertyValue<string>("Name") == "test 1")))
    .Returns(new User{Id = 1});
sessionMock
    .Setup(x => x.Get<User>(
        It.Is<object>(d => d.GetPropertyValue<string>("Name") == "test 2")))
    .Returns(new User { Id = 2 });

Where GetPropertyValue is a little helper:

public static class ReflectionExtensions
{
    public static T GetPropertyValue<T>(this object obj, string propertyName)
    {
        return (T) obj.GetType().GetProperty(propertyName).GetValue(obj, null);
    }
}



回答2:


Moq provided It.IsAny<T> for that case

sessionMock.Setup(x => x.Get<User>(It.IsAny<object>()).Returns(new User());

*dynamic is any object




回答3:


First of all, anonymous objects are not really dynamic.

If you used dynamic objects like

dynamic user1Filter = new ExpandoObject();
user1Filter.Name = "test 1";
var user1 = session.Get<User>(user1Filter);

you could mock it like

sessionMock.Setup(x => x.Get<User>(DynamicFilter.HasName("test 1")));

by implementing custom argument matcher:

static class DynamicFilter
{
    [Matcher] public static object HasName(string name) { return null; }
    public static bool HasName(dynamic filter, string name)
    {
        string passedName = filter.Name; //dynamic expression
        return name.Equals(passedName);
    }
}


来源:https://stackoverflow.com/questions/10458714/how-to-mock-a-method-call-that-takes-a-dynamic-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!