views:

282

answers:

2

Forgive me for my ignorance. I'm trying to learn Rhino.

public Foo(Stream stream)
{
    if (stream == null) throw new ArgumentNullException("woot");
    if (!stream.CanRead) throw new NotSupportedException("sporkish");
    if (!stream.CanSeek) throw new NotSupportedException("monkey");
}

I would like to test this function with a NUnit test by making a test for those exceptions. Is this an appropriate usage of mock objects, or do I actually need to make a special inherited class of Stream? If mocking is appropriate, how do I do this using Rhino? I can figure out how to return dummy values from functions (I think), but not properties.

+4  A: 

This is an appropriate usage of Mocks. You would need three Mock objects. One without stream.CanRead, one without stream.CanSeek, and one with both (to test for success).

Don't forget that this might involve breaking out the functionality of Stream that you're using in to a seperate interface (so that you can build your mock object from the interface).

Justin Niessner
+5  A: 

You can create a mock of Stream which indicates it cannot read and cannot seek, as follows

MockRepository mocks = new MockRepository();

Stream mockStream = mocks.StrictMock<Stream>();

Expect.Call(mockStream.CanRead).Return(false);
Expect.Call(mockStream.CanSeek).Return(false);

mocks.ReplayAll();

// Perform the unit test.

mocks.VerifyAll();

A couple of things of worth to remember about mocking:

  1. Mocking isn't just about creating objects which return dummy values. A good mocking framework tests that a particular member of a class has been accessed. This lets you test to see that the classes you are testing are making the correct calls to dependant objects. In the above example, if you haven't read the value of both CanRead and CanSeek by the time VerifyAll() is called, an exception will be thrown to fail your test.
  2. Mocking is most useful when testing against interfaces. The less behaviour you can override in a particular type, the less effective mocking becomes. In the case of Stream, you can override the properties you are concerned with, and therefore you can achieve your goal of creating a mock quite easily. If you wanted to mock a non-virtual/overrideable property, you would have a harder task.

For your scenario, in order to test the three exceptions are thrown, you will need to create two separate mocks to reach all code paths: one which fails the first assertion (!stream.CanRead) and one which passes the first assertion and fails the second assertion (!stream.CanSeek).

Programming Hero
I see what I was doing wrong now. I was trying to use PropertyBehavior before the .Return(false) calls. I think I misunderstood the usage of PropertyBehavior. I'm still a noob. :)
yodaj007