开发者

Rhino Mocks stubs and mocks are only good for interfaces?

Is it correct that Rhino Mocks stubs and mocks are only good for interfaces, not concrete classes? I spent quite a time trying to make this piece of code working. I did not expect the stubbed pubSubClient to always call Send method from the class. That method has some dependencies and throws exception.

[Test]
public void Test01()
{
    PubSubMessage psm = new PubSubMessage(); 
    var pubSubClient = MockRepository.GenerateStub<PubSubClient>();
    pubSubClient.Stub(x => x.Send(psm)).IgnoreArguments().Return(null);
    // actual PubSubClient Send method throws exception
    // the rest of the te开发者_运维技巧st is skipped...
}

However, when I have extracted the interface and run the same test with IPubSubClient, it seems to be working as expected.

Does it mean that I have to extract the interface for every class I want to mock/stub with Rhino? Or I am missing something, technically or conceptually?

UPDATE: OK, It seems I figured out what part I was missing: Rhino Mocks cannot intercept calls to non-virtual methods. So, I guess I have either use interfaces or make every method on the concrete class virtual. Please correct me if there's another option.


Bryan's answer of using partial mocks is incorrect. That's not what partial mocks are for.

Jon Erickson's answer is mostly correct: Rhino Mocks and Moq can't intercept non-virtual calls, nor can they intercept static methods or properties. That means you can't fake the following:

DateTime.Now; // static property, can't fake static property
someClass.SomeNonVirtualMethod(); // can't fake non-virtual method
sealedClass.Foo(); // can't fake anything on sealed classes
Utilities.SomeStaticMethod(); // can't fake static methods
someList.Any(); // can't fake extension methods like Linq's .Any()

TypeMock can fake these, as Jon mentioned.

It should be noted there is an additional mocking framework that can intercept all calls: the Microsoft Moles framework. It works the same way TypeMock does, it uses the .NET profiler API to intercept calls.

Moles is free (for now). It's also beta. Moles only only works with Microsoft Pex tools. And its API is clearly inferior to TypeMock's refined, elegant API.


You have to make the methods virtual. Rhino mocks (and most other isolation frameworks) utilizes proxy classes in order to create the stubs/mocks.

If you use TypeMock Isolator you can mock anything because this isolation framework utilizes the .NET Profiler API in order to create its' stubs/mocks


That's essentially correct, and is generally good practice. However, it's only really useful for a specific type of coding.

Don't think of objects as things that some 'higher power' can manipulate. Instead, think of them as autonomous 'people' that can send messages to each other. An interface represents the messages sent by a single object.

You then use mocks to verify that the correct messages were sent, not to provide fake implementations of dependencies.

Ideally, you don't create an interface that exactly matches an existing class - instead, the class consuming the interface declares its needs in the form of an interface.


Partial mocks allow you to mock out functionality of a concrete class. See: http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx


I don't think there's another way of doing this other than making any methods you want to mock virtual - I believe the way mocks of concrete classes are created is by dynamically sub-classing the concrete class being mocked and then overriding the given methods with the behaviour you specify in the test, so this requires a virtual method to work correctly.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜