views:

49

answers:

1

I have the following class structure that I need to unit test:

public interface IFoo
{
    int Value { get;}
    int GetValue();
}

public class BaseClass : IFoo
{
    public virtual int Value { get { return 100; } }
    public virtual int GetValue()
    {
        return Value;
    }
}

public class ChildClass : BaseClass, IFoo
{
    public override int GetValue()
    {
        return Value;
    }
}

I am attempting to test the ChildClass.GetValue() method with RhinoMocks.

I have the following stub code:

public ChildClass CreateChildClass(int value)
{
   var childClass = MockRepository.GenerateStub<ChildClass>();
   childClass.Stub(x => x.Value).Return(value);
   return childClass;            
}

And the following UnitTest code:

public IEnumerable<IFoo> CreateList()
{
   yield return CreateChildClass(1000);
   yield return CreateChildClass(2000);
}

[TestMethod]
public void virtualMethodTest()
{
   var list = CreateList();
   var query = from p in list
               select p.GetValue(); //I can't use p.Value

   var sum = query.Sum(p => p);
 }

The issue at hand is the sum is always zero. I can quick watch the list and see the two mock objects with the correct values from the CreateList().

Is it possible to unit test the virtual method on the child class? or do I need to use a different RhinoMocks approach?

Thanks

A: 

Two things:

  • You're creating stubs of the concrete class, not IFoo. Mocks are highly reflective in their inner workings, and so polymorphic calls may or may not behave the same depending on the framework and the exact nature of the call.
  • You're creating stubs, which by their nature will ignore any call (returning the default value for the return type) made to their interface that isn't expected. This is the direct cause of your problem; GetValue() wasn't expected, and so it returns the default integer value (0).

You're looking to test some behavior of the actual class, but to override certain other behavior (side effects, not part of the scope of the test, etc). The basic answer in RhinoMocks is a PartialMock, which will default to the actual class's behavior except where you expect a certain call to be made. So, instead of GenerateStub<>(), create an instance of the MockRepository and instantiate a new MockRepository.PartialMock(). Expect the internal behavior you want to override, but don't touch anything else. You may have to use the older method of recording and playing back; the version of RhinoMocks I normally work with does not behave correctly when you instantiate a PartialMock and then call Expect() on the instance.

The change would be along the lines of:

//instantiate Mocks in class scope, as an instance of MockRepository

public ChildClass CreateChildClass(int value)
{
   var childClass = Mocks.PartialMock<ChildClass>();
   childClass.Expect(x => x.Value).Return(value);
   return childClass;            
}
KeithS