我的测试试图断言某个dal方法被调用,并带有一些参数。 该方法返回一个DataSet
对象,所以当我调用时,我的模拟只返回一个空的DataSet
。在犀牛中混合存根和模拟
我的问题是,当SUT不会调用用适当的参数的dal,模拟将不会返回空DataSet
,所以我的班会扔在试图访问一个空引用异常。这只会导致测试失败,并在测试运行器中显示不相关的消息。
我想存根方法在所有情况下返回空的Dataset
,所以方法将正常运行,并在测试结束时验证它是否与期望的参数一起被调用。我要求太多吗?
我的测试试图断言某个dal方法被调用,并带有一些参数。 该方法返回一个DataSet
对象,所以当我调用时,我的模拟只返回一个空的DataSet
。在犀牛中混合存根和模拟
我的问题是,当SUT不会调用用适当的参数的dal,模拟将不会返回空DataSet
,所以我的班会扔在试图访问一个空引用异常。这只会导致测试失败,并在测试运行器中显示不相关的消息。
我想存根方法在所有情况下返回空的Dataset
,所以方法将正常运行,并在测试结束时验证它是否与期望的参数一起被调用。我要求太多吗?
这应该这样做,假设你的方法有一个int参数。
IDal dalMock = MockRepository.GenerateMock<IDal>();
// setup mock to return the emptyDataSet for any argument
dalMock
.Stub(x => x.GetDataSet(Arg<int>.Is.Anything))
.Return(emptyDataSet)
.Repeat.Any();
sut.Execute()
// assert that the argument had been 7
dalMock.AssertWasCalled(x => x.GetDataSet(Arg<int>.Is.Equal(7))
Documentation of argument constraints.(我写这一章,所以你可以问我,如果你不明白;-)
使用.NET 2.0会是这个样子:
MockRepository mocks = new MockRepository();
IDal dalMock = mocks.CreateDynamicMock<IDal>();
// expect the correct argument
Expect.Call(dalMock.GetDataSet(Arg<int>.Is.Equal(7)))
.Return(emptyDataSet)
.Repeat.Once();
// setup mock to return the emptyDataSet for any argument
SetupResult.For(dalMock.GetDataSet(Arg<int>.Is.Anything))
.Return(emptyDataSet)
.Repeat.Any();
sut.Execute()
// assert that the argument had been 7
mocks.VerifyAll();
不是100%确定它是否有效,但它应该。
你也可以试试这个:
// setup mock to return the emptyDataSet for any argument
SetupResult.For(dalMock.GetDataSet(Arg<int>.Is.Anything))
.Do((GetDataSetDelegate)delegate(int i)
{
Assert.AreEqual(7, i);
}
.Return(emptyDataSet)
.Repeat.Any();
sut.Execute()
Do
当模拟被调用时执行。它需要一个具有与模拟方法完全相同的接口的委托。由于.NET 2.0的语法原因,您需要将其转换为正确的委托类型,因此您需要首先声明它(在这种情况下为GetDataSetDelegate
)。
犀牛3.5用户注意事项:有一个更方便的方法来调用:WhenCalled
只需要一个lambda作为参数,但必须以不同的方式实现。
分别使用Do
或WhenCalled
可以在调用模拟时实现自变量声明。
您是否尝试过使用部分模拟模块与Rhino Mocks描述的here。我想如果你这样做,那么你会得到你想要的。
使用部分模拟是一个非常不好的想法:只有在你需要模拟一些没有界面并且不受你控制的东西时才能使用它们 - 换句话说,如果你非常绝望。 – 2009-07-14 11:54:41
我从来没有说过这是个好主意。这是他有一个问题的想法。那么你最好的想法是什么? – AutomatedTester 2009-07-14 11:59:39