【问题标题】:Ordering method return values with Rhino-Mock stubs使用 Rhino-Mock 存根排序方法返回值
【发布时间】:2011-08-02 08:21:52
【问题描述】:

我在阅读 Roy Osherove 的单元测试的艺术时开始尝试使用 Rhino-Mocks (3.6)。他有一个示例,演示了一个模拟方法可以编写脚本以在使用相同参数调用两次时返回不同的结果:

   [Test]
    public void ReturnResultsFromMock()
    {
        MockRepository repository = new MockRepository();
        IGetRestuls resultGetter = repository.DynamicMock<IGetRestuls>();
        using(repository.Record())
        {
            resultGetter.GetSomeNumber("a");
            LastCall.Return(1);

            resultGetter.GetSomeNumber("a");
            LastCall.Return(2);

            resultGetter.GetSomeNumber("b");
            LastCall.Return(3);

        }

        int result = resultGetter.GetSomeNumber("b");
        Assert.AreEqual(3, result);

        int result2 = resultGetter.GetSomeNumber("a");
        Assert.AreEqual(1, result2);

        int result3 = resultGetter.GetSomeNumber("a");
        Assert.AreEqual(2, result3);
    }

这很好用。但是当我用 Stub 和一个接受并返回字符串的方法尝试同样的事情时,我无法生成第二个返回值:

    [Test]
    public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived()
    {
        MockRepository mocks = new MockRepository();
        IMessageProvider stub = mocks.Stub<IMessageProvider>();

        using (mocks.Record())
        {
            stub.GetMessageForValue("a");
            LastCall.Return("First call");
            stub.GetMessageForValue("a");
            LastCall.Return("Second call");
        }

        Assert.AreEqual("First call", stub.GetMessageForValue("a"));
        Assert.AreEqual("Second call", stub.GetMessageForValue("a"));
    }
}

public interface IMessageProvider
{
    string GetMessage();
    string GetMessageForValue(string value);
}

此测试失败,因为两个呼叫都收到了“First Call”。我尝试了几种语法皱纹(使用 mocks.Ordered()、SetResult、Expect 等),但仍然无法让第二个结果出现。

我做错了什么,还是 Rhino-Mocks 的限制?我检查了这个blog post,但建议的语法并没有解决我的问题。

【问题讨论】:

    标签: c# unit-testing rhino-mocks


    【解决方案1】:

    我认为,如果您正在使用存根,则使用 E​​xpect 不合适,因为您不想要期望而是替代您的依赖项。

    所以我相信如果你使用存根语法会更有意义:

    stub.Stub.(s=>s.GetMessageForValue("a"))
                                .Return("First call").Repeat.Once(); 
    
    stub.Stub.(s=>s.GetMessageForValue("a"))
                                .Return("Second call").Repeat.Any;
    

    【讨论】:

      【解决方案2】:

      你缺少的一点是告诉存根第一个值应该只返回一次:

      ...
      using (mocks.Record())
      {
          stub.GetMessageForValue("a");
          LastCall.Return("First call").Repeat.Once();
          stub.GetMessageForValue("a");
          LastCall.Return("Second call");
      }
      

      当然,除非您对 Repeat 施加其他限制,否则您的“第二次通话”实际上是指“第二次或后续通话”。

      您也可以考虑使用 RhinoMocks 现在提供的较新的 Arrange、Act、Assert (AAA) 语法:

      [Test]
      public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived()
      {
          IMessageProvider stub = MockRepository.GenerateStub<IMessageProvider>();
      
          stub.Expect(mp => mp.GetMessageForValue("a"))
              .Return("First call")
              .Repeat.Once();
          stub.Expect(mp => mp.GetMessageForValue("a"))
              .Return("Second call");
      
          Assert.AreEqual("First call", stub.GetMessageForValue("a"));
          Assert.AreEqual("Second call", stub.GetMessageForValue("a"));
      }
      

      它更简洁一些,通常可以让您不必担心存根的记录播放断言状态。 Derick Bailey 在 Los Techies 上写了article about using Repeat。它也恰好使用 AAA 语法)。

      【讨论】:

      • +1 在文章上...我一直在寻找一个很好的综合解释 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      相关资源
      最近更新 更多