【问题标题】:How to use Rhino.Mocks AssertWasCalled() correctly?如何正确使用 Rhino.Mocks AssertWasCalled()?
【发布时间】:2010-06-25 09:14:28
【问题描述】:

我打电话给_mocks.ReplayAll(),然后是一个或多个_mockedObject.AssertWasCalled(),然后是_mocks.VerifyAll()。但它告诉我“当模拟对象处于记录状态时,此操作无效”。

[Test]
public void SetStateExecuting_Should_Set_State_To_Pause_And_Not_Change_GlobalState_When_GlobalState_Is_Paused()
{
    var task = new Task { ID = 1, TimeZone = -660, GlobalState = TaskState.Paused };
    _taskDataProvider.Expect(p => p.StateUpdate(task.ID, task.TimeZone, TaskState.Paused));
    _mockRepository.ReplayAll();
    _manager.SetStateExecuting(task);
    _taskDataProvider.AssertWasNotCalled(p => p.GlobalStateUpdate(task.ID, 
                                                                  TaskState.Executing));
    _mockRepository.VerifyAll();
}

为了使这些方法正常工作,正确的调用顺序是什么?

【问题讨论】:

    标签: c# nunit rhino-mocks assert


    【解决方案1】:

    Jon Kruger 的博文"How to use rhino mocks documented through tests" 提供了使用 rhino 模拟方法可以做的所有事情的简单示例。他还展示了你不能做的事情,我发现这对学习很有帮助。

    如前所述,使用带有静态构造函数的 Arrange、Act、Assert 语法更易于阅读。博客文章显示了这两种方法的示例。

    以下是 Jon 的示例代码示例:

    新语法:

     [Test]
        public void You_can_check_to_see_if_a_method_was_called()
        {
            var stub = MockRepository.GenerateStub<ISampleClass>();
    
            stub.MethodThatReturnsInteger("foo");
    
            stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"));
            stub.AssertWasCalled(s => s.MethodThatReturnsInteger(Arg<string>.Is.Anything));
        }
    

    旧式:

        [Test]
        public void Calling_virtual_methods_will_call_the_actual_method()
        {
            var mockRepository = new MockRepository();
            var sampleClass = mockRepository.PartialMock<SampleClass>();
            sampleClass.Replay();
    
            sampleClass.VirtualMethod("foo").ShouldEqual(3);
            sampleClass.VirtualMethodWasCalled.ShouldBeTrue();
            sampleClass.AssertWasCalled(c => c.VirtualMethod("foo"));
        }
    

    【讨论】:

      【解决方案2】:

      您正在混合旧的记录/重播模式和新的AAA pattern

      在记录模式下设置“不使用这些参数调用”预期的正常方法如下所示:

      _taskDataProvider.Expect(
          p => p.GlobalStateUpdate(task.ID, TaskState.Executing)).Repeat.Never();
      

      或者,您可以使用严格的模拟,它根本不允许意外调用。

      AssertWasCalledAssertWasNotCalled 用于 AAA,您将断言放在最后。使用 Record/Replay 语法,行为和期望都应该在切换到重播模式之前的开始设置。

      AssertWasNotCalled 可能实际上也可以与 Record/Replay 一起使用,但我从未尝试过,因为我不喜欢混合使用这两种方法的元素。它不必要地使事情复杂化。)

      【讨论】:

        【解决方案3】:

        似乎我找到了解决方案。这似乎有点奇怪,但它确实有效。事实证明,由于某种原因,我需要调用 ReplayAll() 两次...

        这行得通:

        [Test]
        public void SetStateExecuting_Should_Set_State_To_Pause_And_Not_Change_GlobalState_When_GlobalState_Is_Paused()
        {
            var task = new Task { ID = 1, TimeZone = -660, GlobalState = TaskState.Paused };
            _mockRepository.ReplayAll();
            _manager.SetStateExecuting(task);
            _taskDataProvider.AssertWasCalled(p => p.StateUpdate(task.ID, task.TimeZone, TaskState.Paused));
            _taskDataProvider.AssertWasNotCalled(p => p.GlobalStateUpdate(task.ID, TaskState.Executing));
            _mockRepository.ReplayAll();
        }
        

        【讨论】:

        • 您好,可能有助于展示您如何声明 _manager 等。我通常不需要让它如此复杂。还查看您正在测试的代码可能很有用。如果你想得到 Rhino Mocks 的帮助,我必须说我得到了同事的帮助,也来自“单元测试的艺术”一书manning.com/osherove
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多