63

我想设置一个返回值

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true);

但随后在特定测试中,覆盖该期望以返回 false。

就像是:

_stubRepository.ClearExpectations();  //<- this does not exist, I'm just making something up
_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(false);

请注意,我不希望期望在第二次调用时返回 false,我想覆盖第一个期望。

这将有助于大大简化我的测试场景。

4

3 回答 3

79

有以下三种方式:

您可以使用 BackToRecord 重置期望值

我不得不承认我从来没有真正使用过它,因为它很尴尬。

// clear expectations, an enum defines which
_stubRepository.BackToRecord(BackToRecordOptions.All);
// go to replay again.
_stubRepository.Replay();

编辑:现在我有时会使用它,它实际上是最干净的方式。应该有一个扩展方法(如 Stub)来完成它 - 我认为它只是被遗忘了。我建议自己写。

您可以使用 Repeat.Any()

它“破坏”了存根定义的顺序并“覆盖”了以前的定义。但它在某种程度上是隐含的。我有时会使用它,因为它很容易编写。

_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false)
  .Repeat.Any();

您可以创建一个新的模拟

琐碎,但明确且易于理解。如果您想保留大量定义并且只更改一个调用,这只是一个问题。

_stubRepository = MockRepository.GenerateMock<IRepository>();
_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false);
于 2009-04-20T21:06:55.570 回答
22

对于这些情况,我创建了一个简单的 RinoMocks 扩展方法来更好地显示存根的意图并提高可读性。

public static void OverridePrevious<T>(this IMethodOptions<T> options)
{
    options.Repeat.Any();
}

因此,而不是像下面这样可能需要评论的神秘调用:

[SetUp]
public void Setup()
{
    carStub.Stub(x => x.Model).Return("Model1");
    carStub.Stub(x => x.Model).Return("Model2");
}

[Test]
public void SomeTest()
{
    //Arrange
    //overrides previous stubs that were setup for the Model property
    carStub.Stub(x => x.Model).Return(null).Repeat.Any();

    //Act
    //Assert
}

您可以获得更易读的测试,更好地显示 .Repeat.Any() 调用的意图:

carStub.Stub(x => x.Model).Return(null).OverridePrevious();
于 2012-07-02T16:24:51.197 回答
8

为了社区的利益,我将把它添加到上面 Stefan 的选项列表中:

如果需要经常更改返回值,我发现如下使用闭包既干净又高效。

bool returnValue = true;
_stubRepository.Stub(x => x.Contains(null)).IgnoreArguments().Do(new Func<bool>(() => {
    return returnValue;
}));

returnValue = false;
// Calls to Contains now return false;

returnValue = true;
// Calls to Contains now return true;

The lambda expression will be executed every time Contains is called and because we created a closure referencing returnValue, it will always look up the current value of returnValue.

于 2014-07-11T14:58:52.570 回答