5

我有一个我想模拟的依赖项。

public abstract class MyDependency
{
    protected Dictionary<string, object> _outputs = new Dictionary<string, object>();
    public Dictionary<string, object> Outputs
    {
        get
        {
            return _outputs;
        }
    }
}

出于单元测试的目的,我需要公共属性Outputs返回一个已知值。我知道我们不能模拟字段或非虚拟成员。所以,我可以去创建我自己的模拟MyDependency来设置支持字段_outputs

public class MockMyDependency : MyDependency
{
    public MockMyDependency()
    {
        _outputs = new Dictionary<string, object>
        {
            { "key", "value" }
        };
    }
}

但是,是否可以在不显式创建我自己的派生模拟类的情况下使用 Moq 来执行此操作?

4

4 回答 4

4

如果您无法将属性更改为虚拟或定义接口(我假设如果您不能执行第一个,则也无法执行第二个),那么我只看到两个可能的选项:

  • 使用支持模拟非虚拟成员的模拟框架(例如 TypeMock)
  • 像您已经做的那样,创建一个从 MyDependency 继承的特定模拟实现。
于 2013-04-16T13:41:44.300 回答
2

如果您自己不从该类派生,则很难指定该protected字段_outputs,因为它不在范围内并且其名称将无法编译。

但是你当然可以用讨厌的反射来做到这一点:

var mock = new Mock<MyDependency>();

var field = typeof(MyDependency)
    .GetField("_outputs", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(mock.Object,
    new Dictionary<string, object> { { "key", "value" } });

如果你确实派生MyDependency自它,那么在派生自它的类中,你可以直接设置字段,如下所示:

// this code is inside some class which derives from MyDependency
mock.Object._outputs = new Dictionary<string, object> { { "key", "value" } };
于 2013-04-09T20:45:31.097 回答
1

我明白你在问什么,我想你正在寻找这样的东西:

public class Test
{
    public void MockObject()
    {
        var mocked = new Moq.Mock<MyDependency>();
        mocked.CallBase = true;
        mocked.Setup(m => m.Outputs).Returns(new Dictionary<string, object>() { { "key", "value" } });

        mocked.Object.{do something with mocked object};
    }
}

......我认为你仍然需要virtualOutputs财产上。

于 2013-04-09T19:28:42.393 回答
1

声明一个接口,从 MyDependency 类中公开您想要的成员,然后您可以将它与 Moq 一起使用来创建测试所需的行为。

public interface IMyDependency {
    Dictionary<string, object> Outputs { get; }
}

// test...
var dictionary = new Dictionary<string, string>{{"key", "value"}};
var dependency = new Mock<IMyDependency>();
dependency.SetupGet(d => d.Outputs).Returns(dictionary);

当您在生产代码中使用它时,您可以使用DuckTyping(或类似方法)在您的界面后面“投射” MyDependency 实例。

于 2013-04-11T14:46:14.793 回答