订购方法使用Rhino-Mock存根返回值

时间:2011-04-10 03:30:46

标签: c# unit-testing rhino-mocks

我开始尝试使用Rhino-Mocks(3.6),同时阅读Roy Osherove的 The Unit of Unit Testing 。他有一个示例,演示了当使用相同的参数调用两次时,可以使用mocked方法编写脚本以返回不同的结果:

   [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,但建议的语法无法解决我的问题。

2 个答案:

答案 0 :(得分:10)

您缺少的是告诉存根,第一个值应该只返回一次:<​​/ p>

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

当然,你的“第二次通话”实际上意味着“第二次或后续通话”,除非你对重复施加其他限制。

您可能还会考虑使用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 :(得分:1)

我认为如果您正在处理存根,使用Expect不适合您不希望期望,而是替换您的依赖。

所以我相信如果你使用存根语法,那就更有意义了:

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

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