【问题标题】:Rhino mocks stubbing twice the same function doesn't work as expectedRhino 模拟两次相同的函数无法按预期工作
【发布时间】:2016-01-16 16:01:11
【问题描述】:

我最近开始使用 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 存根会有这样的行为,更重要的是我怎样才能以最干净的方式解决它?

【问题讨论】:

  • 这种行为让我大吃一惊。我在许多测试中重用了一个模拟对象。我的一个测试需要模拟来为其中一个存根属性重现不同的结果,所以我只是尝试“覆盖”以前的属性存根,但如下所述,它并不像这样工作。我的解决方案是创建一个单独的模拟对象,而不是重用现有的模拟对象,但我明白这可能不适用于所有情况。

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


【解决方案1】:

当您在RhinoMocks 中指定一个假对象上的行为而没有任何约束(RepeatOnce 等)时,该行为将保持不变,您将无法覆盖它。(实际上,选项 1 显示了您如何做到这一点。 ..)

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

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

以上行将在_worker.Stub(w =&gt; w.DoWork()).Return(expected);之前执行。

SetUp / TestInitialize 属性的最佳做法是在它们中分组您想在所有测试方法中应用的设置。

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

如果你的真实情况更复杂:

选项1:清除模拟

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

// go to replay again.
_worker.Replay();

选项2:限制行为

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

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

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

选项3:创建一个新的fake and CUT(class under test)

【讨论】:

    猜你喜欢
    • 2019-12-24
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多