Rhino.Mocks:方法调用记录器(a.k.a.test spy)

时间:2009-11-08 09:09:49

标签: c# dependency-injection mocking rhino-mocks

我有一个我想要测试的逻辑,它使用依赖注入接口和一个(或多个)void方法,例如:

interface IMyService
{
    void MethodA (MyComplexObject arg1, int arg2);
}

我想要的是为IMyService创建一个存根,只需记录 MethodA的方法调用,之后我就可以将其作为列表,如:

MyComplexObject actualParameter = serviceRecorder
    .GetMethodRecordings("MethodA").GetRecord(10).GetInputParameter(0);

我需要这个来检查某个调用的这个参数的内容并对其进行断言。我知道还有其他的做法(比如设置带有约束的期望调用),但是当你有大量的调用并且你只想在第51个调用时,这似乎更容易编写,例如。

Rhino.Mocks中是否存在某种机制,或者我留给自己的设备(编写具有录制功能的虚拟IMyService实现)?

注意:(我知道这可能导致测试变得脆弱,我知道后果)。

更新:这是我到目前为止所发现的(部分归功于Mark帮助将此模式命名为Test Spy):

2 个答案:

答案 0 :(得分:5)

// arrange
var myServiceStub = MockRepository.GenerateStub<IMyService>();
var myComplexObj = new MyComplexObject 
{
    SomeProp = "something",
    SomeOtherProp = "something else"
};

// act
myServiceStub.MethodA(myComplexObj, 10);

// assert
myServiceStub.AssertWasCalled(
    x => x.MethodA(
        Arg<MyComplexObject>.Matches(
            arg1 => arg1.SomeProp == "something" &&
                    arg1.SomeOtherProp == "something else"
        ), 
        Arg<int>.Is.Equal(10)
    )
);

备注:不要忘记将界面公开,否则Rhino Mocks将无法创建代理。


更新:

抱歉,我没有仔细阅读你的问题。以下是如何获得所需的行为:

var args = myServiceStub.GetArgumentsForCallsMadeOn(
    x => x.MethodA(null, default(int)),
    x => x.IgnoreArguments()
);

var theComplexObjectPassedAtThe51thCall = (MyComlexObject)args[50][0];
// TODO: assert something on this object

答案 1 :(得分:3)

查看Arrange-Act-Assert (AAA) syntax of Rhino Mocks

总体而言,Record-Replay语法已过时。它发明时真是太棒了,但随着lambda表达式的出现,我们得到了更好的东西。

Rhino Mocks 4 is probably not going to support Record-Replay,而是依赖于lambda表达式,Moq也是如此。

最后,记录调用以供以后检查的测试双方称为测试间谍 - 有关详细信息,请参阅xUnit Test Patterns:)