Lee Treveil
Lee Treveil

Reputation: 6845

Rhino Mocks, void and properties

Just starting out with Rhino Mocks and im having a very simple problem, how do I mock a class with a void which sets a property?

class SomeClass : ISomeClass
{
    private bool _someArg;

    public bool SomeProp { get; set; }

    public SomeClass(bool someArg)
    {
        _someArg = someArg; 
    }

    public void SomeMethod()
    {
        //do some file,wcf, db operation here with _someArg
        SomeProp = true/false;
    }
}

Obviously this is a very contrived example, Thanks.

Upvotes: 2

Views: 7952

Answers (4)

Spoike
Spoike

Reputation: 121772

In your example you won't need RhinoMocks because you're apparently testing the functionality of the class under test. Simple unit testing will do instead:

[Test]
public void SomeTest()
{
    var sc = new SomeClass();
        // Instantiate SomeClass as sc object
    sc.SomeMethod();
        // Call SomeMethod in the sc object.

    Assert.That(sc.SomeProp, Is.True );
        // Assert that the property is true... 
        // or change to Is.False if that's what you're after...
}

It's much more interesting to test mocks when you have a class that has dependencies on other classes. In your example you mention:

//do some file, wcf, db operation here with _someArg

I.e. you expect some other class to set SomeClass's property, which makes more sense to mocktest. Example:

public class MyClass {

    ISomeClass _sc;

    public MyClass(ISomeClass sc) {
        _sc = sc;
    }

    public MyMethod() {
        sc.SomeProp = true;
    }

}

The required test would go something like this:

[Test]
public void MyMethod_ShouldSetSomeClassPropToTrue()
{
    MockRepository mocks = new MockRepository();
    ISomeClass someClass = mocks.StrictMock<ISomeClass>();

    MyClass classUnderTest = new MyClass(someClass);

    someClass.SomeProp = true;
    LastCall.IgnoreArguments();
        // Expect the property be set with true.

    mocks.ReplayAll();

    classUndertest.MyMethod();
        // Run the method under test.

    mocks.VerifyAll();
}

Upvotes: 6

Lee
Lee

Reputation: 1115

It's not totally clear from the question what the object you're trying to test is - if you simply want to check that SomeClass.SomeMethod() sets a property then you don't need mocking since you can just do a simple state-based test:

[TestMethod]
public void SomeMethodTest()
{
    SomeClass s = new SomeClass();
    s.SomeMethod();

    Assert.AreEqual(expectedValue, s.SomeProp);
}

Alternatively, if SomeClass is a dependency for some other class, and you want to test the interaction between that class and SomeClass, then you set up the expectation on the method call during the 'Record' section of the test using RhinoMock, like this:

[TestMethod]
    public void CheckInteractionWithSomeClass()
    {
        MockRepository mocks = new MockRepository();
        ISomeClass someClass = mocks.StrictMock<ISomeClass>();

        using (mocks.Record())
        {
            //record expection that someClass.SomeMethod will be called...
            someClass.SomeMethod();
        }

        using (mocks.Playback())
        {
            //setup class under test - ISomeClass is injected through the constructor here...
            ClassUnderTest o = new ClassUnderTest(someClass);

            o.MethodOnClassUnderTestThatShouldCallSomeClass.SomeMethod();

            //any other assertions...
        }
    }

Upvotes: 0

Scott Pedersen
Scott Pedersen

Reputation: 1311

Depends on how much fidelity you'd like in your mock object. The easy way to do it is to not worry about it and write out some dumb expect statements.

[Test]
public void SomeTest()
{
   MockRepository mocks = new MockRepository();
   ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
   using(mocks.Record())
   {
      using(mocks.Ordered())
      {
         Expect.Call(MockSomeClass.SomeProp).Return(false);
         Expect.Call(delegate{MockSomeClass.SomeMethod();});
         Expect.Call(MockSomeClass.SomeProp).Return(true);
      }
   }
}

If you want something that acts more like the real object without a canned set of ordered responses you'll have to set up delegates with the do method on the expect.

delegate bool propDelegate();
delegate void methodDelegate();
private bool m_MockPropValue = false;

[Test]
public void SomeTest()
{
   MockRepository mocks = new MockRepository();
   ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
   using(mocks.Record())
   {
      SetupResult.For(MockSomeClass.SomeProp).Do(new propDelegate(delegate
      {
         return this.m_MockPropValue;
      }));
      Expect.Call(delegate{MockSomeClass.SomeMethod();}).Do(new methodDelegate(delegate
      {
         this.m_MockPropValue = true;
      }));
   }
}

Upvotes: 3

Aaron Powell
Aaron Powell

Reputation: 25099

When your preparing something with either SetupResult.For or Expect.Call you need to ensure that they are virtual, otherwise RhinoMocks will be unable to make its own implementation.

Otherwise it's just a matter of setting the results and doing expected calls as Scott Pedersen has shown

Upvotes: 0

Related Questions