犀牛嘲讽两次相同的功能并没有按预期工作

时间:2015-10-18 07:01:10

标签: c# unit-testing mocking nunit rhino-mocks

我最近开始与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();
}

有人知道为什么Rhino存根以这种方式表现,更重要的是如何以最干净的方式解决它?

1 个答案:

答案 0 :(得分:3)

当您在RhinoMocks中的假对象上指定行为而没有任何约束(RepeatOnce等等)时,行为将保持不变,您将无法覆盖它。(实际上,选项1显示了您的行为方式可以...)

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

_worker.Stub(w=>w.DoWork()).Return(0);

上述行将在_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();

Option2 :限制行为

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

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

for(...; i < num of time; ...)
    _worker.DoWork();

Option3 :创建一个新假和CUT(测试中的类)