如何在 Rhino Mocks 存根中设置默认 return 值

How to set a default return value in a Rhino Mocks stub

假设我想使用 Rhino Mocks 生成以下接口的存根:

public interface IFooBar
{
  string Foo(string bar);
}

我将方法 Foo 存根在我的单元测试套件的一次性设置方法中,以及以下约束:

  var foobar = MockRepository.GenerateStub<IFooBar>();
  foobar.Stub(f => f.Foo(Arg<string>.Is.Equal("string1")))
    .Repeat.Any()
    .Return("result1");
  foobar.Stub(f => f.Foo(Arg<string>.Is.Equal("string2")))
    .Repeat.Any()
    .Return("result2");
  //etc...

目前,如果参数 bar 不符合上述任何约束条件,方法 Foo 将默认 return null。在这些情况下,有什么方法可以告诉它 return 除了 null 之外的其他内容(例如空字符串或其他任意字符串)?

我已经尝试在网上搜索文档、SO 和其他地方,但还没有找到满足我需要的解决方案。

我尝试将其添加到开头,希望对 foobar.Stub 的后续调用会 "override" 在满足更具体的约束时出现此默认行为:

  foobar.Stub(f => f.Foo(Arg<string>.Is.Anything))
    .Repeat.Any()
    .Return(string.Empty);

不幸的是,情况并非如此;添加上述内容会导致 Foo 总是 return 一个空字符串,就好像其他 Foo.Stub 调用的 none 曾经发生过一样。

我可以做相反的事情,在 所有其他 Foo.Stub 调用之后进行上述调用 ,有效地涵盖所有剩余的可能情况。这种方法的缺点是一旦我这样做了,我就不能再添加任何其他可能特定于一个特定单元测试而不是任何其他单元测试的约束。

最坏的情况,我可以将所有常见的 Foo.Stub 调用提取到一个可重用的方法中,以便在每个单元测试开始时调用,然后是更多特定于测试的存根,最后是上面覆盖的存根其余情况。我只是想知道是否有更简单的解决方案。

使用输入参数提供方法实现

Instead of using a .Return() with a simple value, you can provide a full implementation of the method using the .Do() method. This also allows you to get access to the input parameters. If you want, you can define a delegate and just call the delegate.

例如

//Arrange
var foobar = MockRepository.GenerateStub<IFooBar>();
foobar.Stub(_ => _.Foo(Arg<string>.Is.Anything))
  .Repeat.Any()
  .Do((Func<string, string>)(input => {
      if (input == "string1") {
          return "result1";
      } else if (input == "string2") {
          return "result2";
      }
      return string.Empty; // or some other arbitrary string
  }));

//Act & Assert to prove it works (using FluentAssertions)
foobar.Foo("string1").Should().Be("result1");
foobar.Foo("string2").Should().Be("result2");
foobar.Foo(null).Should().Be(string.Empty); // or some other arbitrary string