如何模拟采用动态对象的方法调用

时间:2012-05-05 03:57:16

标签: c# mocking moq rhino-mocks

说我有以下内容:

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

我有以下要测试的代码:

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

我该怎么模仿这个电话?

使用Moq,我厌倦了这样做:

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

这不起作用。返回的结果为null

我还尝试使用Rhino Mocks执行以下操作:

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

也没有运气。再次空虚。

那我该怎么做呢?

谢谢,

3 个答案:

答案 0 :(得分:26)

您可以将It.Is<object>匹配器与反射结合使用。您不能在表达式树中使用动态,因此It.Is<dynamic>将无效,这就是您需要反射以按名称获取属性值的原因:

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

GetPropertyValue是一个小帮手:

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

答案 1 :(得分:1)

Moq为该案件提供了It.IsAny<T>

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

* dynamic是任何对象

答案 2 :(得分:1)

首先,匿名对象实际上不是dynamic

如果您使用了dynamic个对象,例如

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

一样嘲笑它
sessionMock.Setup(x => x.Get<User>(DynamicFilter.HasName("test 1")));

通过实现自定义参数匹配器:

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