Rhino 模拟存根两次相同的函数无法按预期工作

sil*_*ver 5 c# nunit unit-testing rhino-mocks mocking

我最近开始使用Rhino,遇到了一种非常意想不到的行为,我无法克服。

问题是我有一个存根基础设施,在我的一项测试中,我需要更改预定义存根之一(在我的基础设施中)以返回与默认值不同的值。

我在以下代码中重现了该问题:

[TestFixture]
public class UnitTest1
{
    private IWorker _worker;

    [SetUp]
    void Setup()
    {
        _worker = MockRepository.GenerateStub<IWorker>();
        _worker.Stub(w=>w.DoWork()).Return(0);
    }

    [Test]
    public void DoWork_StubbingFunctionTwice_CallingTheLastStub()
    {
        int expected = 1;
        _worker.Stub(w => w.DoWork()).Return(expected);
        int actual =_worker.DoWork();
        Assert.AreEqual(expected, actual);
    }

}

public interface IWorker
{
    int DoWork();
}
Run Code Online (Sandbox Code Playgroud)

有人知道为什么犀牛存根会这样,更重要的是我怎样才能以最干净的方式解决它?

Old*_*Fox 4

当您在没有任何约束(RepeatOnce 等)的情况下在假对象上指定行为时,RhinoMocks该行为将保留并且您将无法覆盖它。(实际上选项 1 显示了如何可以...)

在您的情况下,您在方法中指定特定行为Setup:

_worker.Stub(w=>w.DoWork()).Return(0);
Run Code Online (Sandbox Code Playgroud)

上面的行将在 之前执行_worker.Stub(w => w.DoWork()).Return(expected);。

SetUp/属性的最佳实践是仅将您想要在所有测试方法TestInitialize中应用的设置分组到其中。

默认情况下,任何具有返回值的方法都会返回,default(T)因此您可以删除_worker.Stub(w=>w.DoWork()).Return(0);,然后任何事情都会起作用。

如果您的实际情况更复杂:

选项1:清除模拟

// clear expectations, an enum defines which
_worker.BackToRecord(BackToRecordOptions.All);

// go to replay again.
_worker.Replay();
Run Code Online (Sandbox Code Playgroud)

选项2:限制行为

_worker.Stub(w=>w.DoWork()).Return(0).Repeat.Once(); // or the max time you need...
Run Code Online (Sandbox Code Playgroud)

然后在测试方法中添加一个循环:

for(...; i < num of time; ...)
    _worker.DoWork();
Run Code Online (Sandbox Code Playgroud)

选项3:创建一个新的假货并CUT(被测类)