我最近开始与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存根以这种方式表现,更重要的是如何以最干净的方式解决它?
答案 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(测试中的类)