18

我可以在运行时更改存根的行为吗?就像是:

    public interface IFoo { string GetBar(); }
    [TestMethod]
    public void TestRhino()
    {
        var fi = MockRepository.GenerateStub<IFoo>();
        fi.Stub(x => x.GetBar()).Return("A");
        Assert.AreEqual("A", fi.GetBar());
        fi.Stub(x => x.GetBar()).Return("B");
        Assert.AreEqual("B", fi.GetBar());    // Currently fails here
    }

我的代码示例在给定行中仍然失败,fi.GetBar()仍然返回"A".

或者是否有另一个技巧来模拟行为随时间变化的存根?我宁愿不诉诸使用fi.Stub(...).Do(...).

啊,可能我只需要精美手册的硬拷贝,以便有人用它打我的头。看起来应该很明显,但我找不到。

4

1 回答 1

27

警告

改变存根的行为是一种代码味道!

它通常表明您的单元测试太复杂、难以理解并且很脆弱,在对被测类进行正确更改时很容易崩溃。

查看:

  • [xUnit 测试模式][1]
  • [单元测试的艺术][2]

所以,请:只有在无法避免的情况下才使用此解决方案。在我看来,这篇文章几乎是一个糟糕的建议——但是在极少数情况下你真的需要它。


啊,我自己想通了。Rhino 支持录制/回放模式。虽然 AAA 语法始终将对象保持在重放模式,但我们可以切换到记录并返回重放,以清除存根的行为。

它看起来有点hackish,但是......

    public interface IFoo { string GetBar(); }
    [TestMethod]
    public void TestRhino()
    {
        var fi = MockRepository.GenerateStub<IFoo>();
        fi.Stub(x => x.GetBar()).Return("A");
        Assert.AreEqual("A", fi.GetBar());

        // Switch to record to clear behaviour and then back to replay
        fi.BackToRecord(BackToRecordOptions.All);
        fi.Replay();

        fi.Stub(x => x.GetBar()).Return("B");
        Assert.AreEqual("B", fi.GetBar());
    }

更新:

我将来会使用它,所以看起来会更好一些:

internal static class MockExtension {
    public static void ClearBehavior<T>(this T fi)
    {
        // Switch back to record and then to replay - that 
        // clears all behaviour and we can program new behavior.
        // Record/Replay do not occur otherwise in our tests, that another method of
        // using Rhino Mocks.

        fi.BackToRecord(BackToRecordOptions.All);
        fi.Replay();
    }
}
于 2009-03-10T13:24:35.120 回答