Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RhinoMock - Use a real object, but stub a single method

I'm writing a unit test against an MVC Controller that has a dependency on IFoo. Foo (the implementation) has one method I'd like to stub, but I want to leave the other intact. How can I set this up using RhinoMock?

Foo has several dependencies that I'd prefer not to mock to save writing additional lines of code and cluttering my test.

Foo :

public interface IFoo{
    int Method1();
    int Method2();
}

public class Foo : IFoo{
   //lot's of dependencies
   public Foo(IBar bar, IBaz baz, IStackOverflow so){}
}

Test:

[Test]
public void What_I_Have_So_Far(){
    //arrange
    //load the real IFoo from Ninject (DI)
    var mockFoo = new Ninject.Kernel(new MyExampleModule())
                    .Get<IFoo>();

    //I want this test to use the real Method1, but not Method2
    //so stub Method2
    mockFoo
       .Stub(x => x.Method2()) //<---- blows up here
       .Returns(42);

    //act
    var controllerUnderTest = new Controller(mockFoo);

Error:

Using this approach, RhinoMock throws an Exception:

System.InvalidOperationException : The object 'MyApplication.MyExampleModule' is not a mocked object.

Question:

How can I stub method2?

I know I could create IFoo as a mock via MockRepository.GenerateMock, but then'd I'd have to copy the real implementation of Method1.


Update:

Both Brad and Jimmy's solution seam to work equally well, I picked Brad's only because it was less code to write.

However, after researching this a bit further, it looks like what I need is an AutoMocker. There seams to be one for StructureMap and Moq, but not RhinoMocks: https://github.com/RhinoMocks/RhinoMocks/issues/3

like image 630
Philip Pittle Avatar asked Sep 27 '22 18:09

Philip Pittle


1 Answers

You have to do it the other way around. Create mocked IFoo and redirect some calls to real IFoo (this has to be done via WhenCalled extension):

var realFoo = new Ninject.Kernel(new MyExampleModule()).Get<IFoo>();
var mockFoo = MockRepository.GenerateStub<IFoo>();

mockFoo.Stub(f => f.Method2()).Return(42);
mockFoo.Stub(f => f.Method1())
   .WhenCalled(invocation =>
   {
       invocation.ReturnValue = realFoo.Method2();
   })
   .Return(whateverValue);

The final Return is required even though we override it few lines before. Otherwise Rhino will throw exception.

like image 198
k.m Avatar answered Oct 09 '22 02:10

k.m