如何清除对象的先前期望?

Geo*_*uer 62 .net rhino-mocks

我想设置一个返回值

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true);
Run Code Online (Sandbox Code Playgroud)

但是在特定测试中,覆盖该期望返回false.

就像是:

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

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

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

Ste*_*ger 78

有三种方式:

您可以使用BackToRecord重置期望值

我不得不承认我从未真正使用它,因为它很尴尬.

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

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

你可以使用Repeat.Any()

它"打破"存根定义的顺序并"覆盖"先前的定义.但它有些含蓄.我有时会使用它,因为它很容易编写.

_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false)
  .Repeat.Any();
Run Code Online (Sandbox Code Playgroud)

您可以创建一个新的模拟

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

_stubRepository = MockRepository.GenerateMock<IRepository>();
_stubRepository.Stub(x => x.Contains(null))
  .IgnoreArguments()
  .Return(false);
Run Code Online (Sandbox Code Playgroud)

  • public static void ResetExpectations <T>(this T mock)其中T:class {mock.BackToRecord(BackToRecordOptions.Expectations); mock.Replay(); 我有一堆方便的犀牛模拟扩展我应该放在谷歌代码实际上.. (5认同)
  • 如果您对模拟对象设置了多个期望并且您只想重置其中一个,该怎么办?Repeat.Any选项是唯一的吗? (4认同)

MoM*_*oMo 22

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

public static void OverridePrevious<T>(this IMethodOptions<T> options)
{
    options.Repeat.Any();
}
Run Code Online (Sandbox Code Playgroud)

因此,而不是像以下可能需要评论的神秘电话:

[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
}
Run Code Online (Sandbox Code Playgroud)

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

carStub.Stub(x => x.Model).Return(null).OverridePrevious();
Run Code Online (Sandbox Code Playgroud)

  • 为了保持选项打开以链接存根配置,扩展方法不应该返回IMethodOptions <T>吗?`public static IMethodOptions <T> OverridePrevious <T>(此IMethodOptions <T>选项){return options.Repeat.Any(); }`. (5认同)
  • @PHeiberg - 我没有尝试过,或者有必要保持'连锁开放',但是我认为你是对的.好点子. (2认同)

Mic*_*ahn 7

为了社区,我将添加此内容以添加到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;
Run Code Online (Sandbox Code Playgroud)

每次Contains调用时都会执行lambda表达式,因为我们创建了一个闭包引用returnValue,它将始终查找当前的returnValue.