Moq:设置没有setter的属性?

Sve*_*ven 17 c# unit-testing properties moq

我有以下课程:

public class PairOfDice
{
    private Dice d1,d2;
    public int Value 
    {
       get { return d1.Value + d2.Value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想PairOfDice在我的测试中使用a 返回值1,虽然我在我的真实骰子中使用随机值:

[Test]
public void DoOneStep ()
{
    var mock = new Mock<PairOfDice>();
    mock.Setup(x => x.Value).Return(2);
    PairOfDice d = mock.Object;
    Assert.AreEqual(1, d.Value);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是我收到了Invalid setup on non-overridable member错误.在这种情况下我该怎么办?

请注意,这是我第一次尝试实施单元测试.

Jim*_*son 49

您可以.SetupGet在模拟对象上使用.

例如.

[Test]
public void DoOneStep ()
{
    var mock = new Mock<PairOfDice>();
    mock.SetupGet(x => x.Value).Returns(1);
    PairOfDice d = mock.Object;
    Assert.AreEqual(1, d.Value);
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见此处

  • 无论是正确的答案,SetupGet都是正确的方法.创建一个永远不会被覆盖或不需要的字段的虚拟,是非常愚蠢的,并且可能违反了开发人员想要保护的内容.这是一个简单的问题,并且使字段虚拟可能几乎没有影响,但在现实世界中,制作虚拟的东西以便您可以测试它是不正确的,这就是您可以使用SetupGet模拟值的原因. (6认同)
  • 仍有完全相同的问题,如上所述问题是它不是虚拟的. (4认同)
  • 您可以为该类创建一个接口,然后使用和模拟该接口,从而消除不必要的虚拟化的要求。如果需要的话,使用接口而不是具体的类来编写测试要好得多。+ IoC...旁注:将超链接放在“此处”对于屏幕阅读器来说很烦人。 (2认同)

Are*_*ren 15

你的问题是因为它不是virtual.不是因为你没有二传手.

Moq无法构建代理,因为它无法覆盖您的属性.您需要使用接口,虚拟方法或抽象方法.

  • 这个答案现在已经过时,因为Moq能够模拟非虚拟属性. (4认同)
  • @krillgar 你能提供一个包含更多文档的链接吗? (4认同)
  • 只有当你认为子类"覆盖"这个函数是一种风险时.基本上没什么值得注意的,除非它是一个超级安全的功能,你不能相信其他课程是正确的,但那些你不应该嘲笑,因为他们不会公开. (2认同)