如何使用 Times() 方法为 RhinoMocks 中的方法调用设置 maximum/upper 绑定?

How to set a maximum/upper bound for method calls in RhinoMocks with the Times() method?

我正在尝试测试一个方法被调用了 3 到 4 次:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using StructureMap.AutoMocking;

namespace AutoMockPlayground
{
    [TestClass]
    public class SomeTests
    {
        [TestMethod]
        public void Bara_ShouldBeCalledThreeOrFourTimes()
        {
            var autoMocker = new RhinoAutoMocker<Foo>(MockMode.AAA);

            var barMock = autoMocker.Get<IBar>();

            // Bara() should not be called more than four times
            barMock.Stub(bar => bar.Bara()).Repeat.Times(3, 4);

            autoMocker.ClassUnderTest.DoSomeThing();

            barMock.VerifyAllExpectations();
        }
    }

    public interface IBar
    {
        void Bara();
    }

    public class Foo
    {
        private readonly IBar _bar;

        public Foo(IBar bar)
        {
            _bar = bar;
        }

        public void DoSomeThing()
        {
            _bar.Bara();
            _bar.Bara();
            _bar.Bara();
            _bar.Bara();
            _bar.Bara();
        }
    }
}

我正在使用 Repeat.Times(int min, int max),但 max 参数似乎没有任何效果。 虽然 Bara() 被调用了 5 次,但是这个测试通过了。

如何在我的测试中表达 Bara() 应该被调用 3 到 4 次?

我不熟悉 RhinoAutoMocker,但看起来 barMock 被用作存根对象而不是模拟对象。

如果它是存根(即通过使用 .Stub()),则调用 VerifyAllExpectations() 将无效。相反,它需要是一个模拟对象,调用 VerifyAllExpectations() 应该有效。

例如,这是我在测试中使用模拟的方式。

var mockObject = MockRepository.GenerateMock<IFoo>();

mockObject.Expect(o => o.CallSomething().Repeat.Times(1);

mockObject.VerifyAllExpecttions();

所以

barMock.Stub(bar => bar.Bara()).Repeat.Times(3, 4);

你能做到吗

barMock.Expect(bar => bar.Bara()).Repeat.Times(3, 4);

编辑:

只是为了扩展:

存根

存根是您不打算对其进行任何断言的对象。您使用存根插入方法 return 值的默认值,或存根调用 void 方法。

在存根对象上调用 .Verfiyxxxx 不会有任何效果,因为根据定义,存根不会跟踪该对象是如何交互的,它只知道 "When method x() is called, do this other action instead".

模拟

如果您希望断言与某个对象的交互,例如一个方法被调用了 4 次,或者一个方法被调用了一组特定的参数,那么你需要一个模拟对象。使用模拟需要调用 Expect(这取决于您使用的模拟框架,但通常是 Expect

根据定义,存根不会检查期望值,另请参阅 this
但是,您可以简单地通过调用 AssertWasCalled
来验证预期 您可以按如下方式修改您的代码:

    var autoMocker = new RhinoAutoMocker<Foo>(MockMode.AAA);

    var barMock = autoMocker.Get<IBar>();

    autoMocker.ClassUnderTest.DoSomeThing();

    // Bara() should not be called more than four times
    barMock.AssertWasCalled(bar => bar.Bara(),     
                            options => options.IgnoreArguments().Repeat.Times(3,4));