我可以使用Moq设置字段的值吗?

时间:2013-04-09 19:16:41

标签: c# .net mocking moq

我有依赖,我想嘲笑。

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 个答案:

答案 0 :(得分:4)

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

  • 使用支持模拟非虚拟成员的模拟框架(例如TypeMock)
  • 创建一个继承MyDependency的特定模拟实现。

答案 1 :(得分: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" } };

答案 2 :(得分: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};
    }
}

...我认为你仍然需要在virtual财产上Outputs

答案 3 :(得分: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实例。