【问题标题】:How to mock a function call on a concrete object with Moq?如何使用 Moq 模拟对具体对象的函数调用?
【发布时间】:2011-01-28 14:07:58
【问题描述】:

如何在 Moq 中做到这一点?

Foo bar = new Foo();
Fake(bar.PrivateGetter).Return('whatever value')

似乎我只能找到如何模拟通过框架创建的对象。我只想在我创建的具体对象上模拟一个方法/属性。

在 TypeMock 中,我只会使用 Isolate.WhenCalled(bar.PrivateGetter).Returns('whatever value')

有什么想法吗?

【问题讨论】:

    标签: unit-testing mocking tdd moq


    【解决方案1】:

    您应该使用 Moq 创建您的 Mock 对象并将 CallBase 属性设置为 true 以使用对象行为。

    来自 Moq 文档: CallBase 被定义为“如果没有期望覆盖成员,则调用基类实现。这称为“部分模拟”。它允许模拟类的某些部分,而不必模拟所有内容。

    示例代码:

        [Test]
        public void FailintgTest()
        {
            var mock = new Moq.Mock<MyClass>();
            mock.Setup(m => m.Number).Returns(4);
            var testObject = mock.Object;
            Assert.That(testObject.Number, Is.EqualTo(4));
            Assert.That(testObject.Name, Is.EqualTo("MyClass"));
        }
    
        [Test]
        public void OKTest()
        {
            var mock = new Moq.Mock<MyClass>();
            mock.Setup(m => m.Number).Returns(4);
            mock.CallBase = true;
            var testObject = mock.Object;
            Assert.That(testObject.Number, Is.EqualTo(4));
            Assert.That(testObject.Name, Is.EqualTo("MyClass"));
        }
    
        public class MyClass
        {
            public virtual string Name { get { return "MyClass"; } }
    
            public virtual int Number { get { return 2; } }
        }
    

    【讨论】:

    • 谢谢,我会试试这个。不过让 TypeMock 看起来越来越诱人。啊!
    • 这不起作用 - 它在 mock.Setup() 行(在第二个示例中)“测试方法 CRMFundOfFundPluginsUnitTest.FoFPluginBaseTest.SetMissingTargetValuesTest1 引发异常:System.ArgumentException: Invalid setup on a不可覆盖的成员:m => m.InputTargetDE."。知道为什么吗?
    • 确保您模拟的方法是虚拟的,以便 Moq 能够覆盖它们。
    • 这实际上并没有回答问题。 -- 这会调用基本方法,但它要求您让 Moq 创建对象。 -- OP 展示的场景在外部创建了模拟对象。
    • 也许不回答这个问题,但它在很多情况下已经足够接近并且为我解决了问题。
    【解决方案2】:

    只有 TypeMock Isolator(也许还有 Moles)才能执行这些特技。普通动态模拟库可以only mock virtual and abstract members

    【讨论】:

    • 很高兴知道 - 希望有更多关于 Moles 的信息 - 就人们在 SO 上使用它而言,还没有听到任何关于它的消息
    • FWIW,这里是官方网站:research.microsoft.com/en-us/projects/moles
    • Moq 无法做到这一点已经不再正确。
    • @MushinNoShin 哦,我不知道!能给个链接吗?
    • @MushinNoShin 是的,并确保还阅读了 OP 中的 cmets:“这不起作用”。该答案解释了如何 Moq 虚拟会员,而 OP 询问私人会员。我(已接受)答案中的链接解释了技术上可行的方法。
    【解决方案3】:

    只要签名上的类型可见,Moles 也可以替换私有方法。所以在这种情况下,它看起来像这样:

    MFoo bar = new MFoo { // instantiate the mole of 'Foo'
        PrivateGetterGet = () => "whatever value" // replace PrivateGetter {get;}
    };
    Foo realBar = bar; // retrive the runtime instance
    ...
    

    如果您正在寻找有关 Moles 的更多信息,请从 http://research.microsoft.com/en-us/projects/pex/documentation.aspx 的教程开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多