如何为 类 使用 Moq 的 SetReturnsDefault 方法?

How can I use Moq's SetReturnsDefault method for classes?

在努力让 Moq 的 SetReturnsDefault 方法与我的测试一起工作大约一个小时后,我直接从 Moq 的版本 4 存储库中复制了一个测试:

    // I didn't copy this part:
    public interface IFoo
    {
        public int Value { get; set; }
    }

    // Just this part:
    [Fact]
    public void ReturnsDefaultValueOnProperty()
    {
        var mock = new Mock<IFoo>();
        mock.SetReturnsDefault(int.MinValue);

        Assert.Equal(int.MinValue, mock.Object.Value); 
        // Passes ✔
    }

哪个有效。但是,当我将接口 IFoo 换成 class Foo 时,它失败了:

    public class Foo
    {
        public int Value { get; set; }
    }

    [Fact]
    public void ReturnsDefaultValueOnProperty()
    {
        var mock = new Mock<Foo>();
        mock.SetReturnsDefault(int.MinValue);

        Assert.Equal(int.MinValue, mock.Object.Value); 
        // ❌ Assert.Equal() Failure Expected: -2147483648 Actual: 0
    }

我的猜测是,当它使用 Foo 的默认构造函数时,Value 设置为 default(int),Moq 必须查看并决定它不需要使用 SetReturnsDefault 的默认值?大多数(如果不是全部)我正在测试的 classes 看起来像 Foo:如何在不更改 classes 本身的情况下为 Moq 中的属性设置默认值?

特别是,我想为 classes 中的所有 stringobject 属性设置默认字符串值。

你不能。

正如 Nkosi 指出的那样,Moq 只能与可覆盖的成员(virtualabstract)一起工作。我最终在每次测试时都实例化了我的模型,这是我一开始就应该做的(我只是懒惰)。如果你真的想自动为你的模型赋值而不改变它们的结构,你可能想在一个辅助方法中使用反射来比较 class 属性 类型来赋值:

foreach (var property in foo.GetType().GetProperties()) 
{
    if (property.PropertyType == typeof(string)) {
        property.SetValue(foo, "default value");
    }
    // etc...
}

这是不言而喻的,但如果您走那条路,请尽可能保持简单,以避免在测试代码中引入错误。