RhinoMocks

Few simple mocking scenarios

July 3, 2010 RhinoMocks, TDD, UnitTesting No comments

Are you married? Yeah, quite not usual question for blog post about mocking, but if you are married you probably asked your girl to become your wife.

So you are playing role of PotentialHasband:

    public interface IPotentialHusband
    {
        string
AskForHerHandInMarriage();
    }

and she is PotentialWife, taking your ask into consideration and answering you true or false.

    public interface IPotentialWife
    {
        bool
GiveHimAnswer(string hisSpeech);
    }

If she is Linda, you would need to have “I love you” in your speech to get her agreement:

    public class Linda : IPotentialWife
   
{
        public
bool GiveHimAnswer(string hisSpeech)
 
      {
            return hisSpeech.Contains(“I love you”);
        }
    }
Btw, if your wife is indeed Linda, you just need  put some comments below :)

What we are going to test is to see that after you asked, she will definitely give you at least some answer and not ignore you. Also if her answer is “YES” we would like to see MarriageService called Marry method.

    public class MarriageService
    {
        public virtual void
Marry(IPotentialHusband
almostHusband, IPotentialWife
almostWife)
        {
            Console.WriteLine(“You are now husband and wife!”);
        }
    }

Class which we are going to test is named LearningMocking and has constructor that accepts potential husband/wife and marriageService. Whole story takes place in RestaurantDinner method.

First let’s test that after you asked she gives at least some answer. Since we are not interested in concrete instances we just generate mocks for our interfaces, and passing null instead of marriage service. I’m using RhinoMocks in this example.

        [Test]
        public void EnsureThatAfterHeAskedSheAnswers()
        {
            var potentialHusband = MockRepository.GenerateMock<IPotentialHusband>();
            var
potentialWife = MockRepository.GenerateMock<IPotentialWife>();
            var
learningRhino = new LearningMocking(potentialHusband,
potentialWife, null);
           
learningRhino.RestaurantDinner();
            potentialHusband.AssertWasCalled(x
=> x.AskForHerHandInMarriage());
         
  potentialWife.AssertWasCalled(y => y.GiveHimAnswer(Arg<string>.Is.Anything));
     
  }

This ensured that at least she will give you some answer. In next test we will have some mix and will use concrete class Linda. We have generated Stub for return value of your speech, so instead of
writing concrete class for husband we’ve used stub. This test shows that
she will not marry you:

        [Test]
        public void EnsureLindaWillRejectHim()
        {
            var potentialHusband = MockRepository.GenerateMock<IPotentialHusband>();
            var
linda = new Linda();
         
  var marriageService = MockRepository.GenerateStub<MarriageService>();
            var
learningRhino = new LearningMocking(potentialHusband,
linda, marriageService);
           
potentialHusband.Stub(x => x.AskForHerHandInMarriage())
                .Return(“Hey lady, would you marry me?”);
           
learningRhino.RestaurantDinner();
            marriageService.AssertWasNotCalled(x
=>
                x.Marry(Arg<IPotentialHusband>.Is.Anything,
Arg<IPotentialWife>.Is.Equal(linda)));
        }

Let’s use another strategy to ask Linda:

        [Test]
        public void GiveHimAnotherTry()
        {
            var potentialHusband = MockRepository.GenerateMock<IPotentialHusband>();
            var
linda = new Linda();
         
  var marriageService = MockRepository.GenerateStub<MarriageService>();
            var
learningRhino = new LearningMocking(potentialHusband,
linda, marriageService);
           
potentialHusband.Stub(x => x.AskForHerHandInMarriage())
                .Return(“Linda, I love you, would you marry
me?”
);
   
        learningRhino.RestaurantDinner();
            marriageService.AssertWasCalled(x
=> 
                x.Marry(Arg<IPotentialHusband>.Is.Anything,
Arg<IPotentialWife>.Is.Equal(linda)));
        }

Except of verifying that Marry method was called we also verify that it was called with instance of linda and none else with line Arg<IPotentialWife>.Is.Equal(linda). As well you could setup constructor arguments for MarriageService, since it is not an interface. Also with Rhino.Mocks you will need to have method Marry to be virtual. If it is not virtual and you don’t have interface for it you may need to extend that class with your own.

In the end we’ve got this method:

        public
void RestaurantDinner()
        {
            string wouldYou =
PotentialHusband.AskForHerHandInMarriage();
 
          if(PotentialWife.GiveHimAnswer(wouldYou))
            {
         
      MarriageService.Marry(PotentialHusband, PotentialWife);
            }
        }

Nice picture:

Please write down if you would like to see more complex mocking examples.


No comments


Use Arg ONLY within a mock method call while recording

November 15, 2009 RhinoMocks No comments

If you see this error when testing with RhinoMocks

System.InvalidOperationException: Use Arg<T> ONLY within a mock method call while recording. 0 arguments expected, 2 have been defined.

ensure that method on which you setuped expectation is virtual.
Actually this should be all you need.

I faced this when doing test like this:

[Test]
public void Start_Service_InitializeWasCalled()
{
    var service = MockRepository.GenerateMock<SpecificServiceBase>();
    //some setup here…
    service.Expect(x => x.Initialize(Arg<ServiceSettingElement>.Is.Anything, Arg<LogDelegate>.Is.Anything)).Repeat.Once();

    serviceControllerBase.Start();

    service.VerifyAllExpectations();
}

As you see I’m trying to verify that method Initialize was called after Start was triggered. Signature of method looks like:

public void Initialize(ServiceSettingElement configuration, LogDelegate logDelegate){}

After I changed it to:

public virtual void Initialize(ServiceSettingElement configuration, LogDelegate logDelegate){}

My test passed ok.

I want to mention that when testing with RhinoMocks you always need to pay attention on things like virtual methods, using interfaces instead of classes, also using protected instead of private to have possibility test those stuff with RhinoMocks.


No comments