开发者

Rhino.Mocks: method calls recorder (a.k.a. test spy)

I have a piece of logic I want to test and it uses dependency injected interface with one (or more) void methods, example:

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

What I would want is to create a stub for this IMyService that would just record the method invocations of MethodA and I would later be able to access it as a list, something like:

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

I need this to examine the contents of such a parameter for a certain invocation and make assertions on it. I know there are other was of doing it (like setting expectation calls with constraints), but开发者_JS百科 this seems much easier to write for cases when you have a lot of invocations and you want to make assertions on the 51th one only, for example.

So is there some sort of mechanism in Rhino.Mocks for this or am I left to my own devices (writing dummy IMyService implementation with recording capabilities)?

NOTE: (I'm aware this could lead to tests being fragile and I'm aware of the consequences).

UPDATE: here's what I found so far (thanks in part to Mark's help in naming this pattern as Test Spy):

  • Advanced mocking: anonymous test spy
  • Perhaps using Windsor Castle's interceptors?


// 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)
    )
);

Remark: Don't forget to make the interface public or Rhino Mocks won't be able to create a proxy.


UPDATE:

Sorry I didn't read your question carefully. Here's how to get the desired behavior:

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


Take a look at the Arrange-Act-Assert (AAA) syntax of Rhino Mocks.

In overall, the Record-Replay syntax is obsolete. It was fantastic when it was invented, but with the advent of lambda expressions we got something even better.

Rhino Mocks 4 is probably not going to support Record-Replay, but instead relies on lambda expressions, and so does Moq.

Finally, a Test Double that records invocations for later inspection is called a Test Spy - see xUnit Test Patterns for more information :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜