Search code examples
c#unit-testingrhino-mocks

Unit Testing with RhinoMock: Call method from CuT in expected call statement


Actually I am writing unit tests and for this I use RhinoMocks.

Testmethod:

{
   ...
   var classA = repo.StrictMock<IMyInterface>();
   Expect.Call(()=>classA.AddItem()). // call here method cuT.ItemAdded()
   repo.ReplayAll();

   // test
   cuT.DoSomething(classA);

   ...
}

Class under test:

{
   ...
   public void DoSomething(IMyInterface myInterface)
   {
      myInterface.AddItem();
   }

   public void ItemAdded(object sender, ItemEventArgs e)
   {
     UpdateModel(); // update model only if item wasn't added by AddItem() method called from DoSomething()..
     ...
   }
}

My question is, how do I have to define the Expect.Call() statement so that by calling the expected method AddItem() on the interface a call on cuT.ItemAdded() is raised.

Thanks in advance for your help!

Regards, rhe1980


Solution

  • What you really want here is two tests, as using event indicates that adding items can happen from different source (than DoSomething method):

    // 1: This test will simply verify that tested method calls dependency
    public void DoSomething_AddsItemOnMyInterface()
    {
        var myInterface = MocksRepository.GenerateMock<IMyInterface>();
        myInterface.Expect(m => m.AddItem()).Repeat.Once();
    
        cut.DoSomething(myInterface);
    
        myInterface.VerifyAllExpectations();
    }
    
    // 2: Here we assure that model gets updated when item was added
    public void ItemAdded_UpdatesModel_WhenMyInterfaceRaisesEvent()
    {
        var myInterface = MocksRepository.GenerateMock<IMyInterface>();
        myInterface.Expect(m => m.AddItem()).Repeat.Once();
    
        myInterface.Raise(m => m.ItemAddedEvent += null, myInterface,
            new ItemEventArgs());
    
        // How exactly model is updated when event is raised? The 'how'
        // should be asserted here.
    }
    

    For example, if UpdateModel was setting your class property to some value, you would assert that. If it was clearing some collection, in assert you'd check that collection is empty. The event itself is not interesting from testing point of view (think of it as a condition); what's interesting is what happens (contract) when that event is raised. And test should check that the contracted what happened indeed.

    Btw, syntax you use (Record-Replay) is a bit old one. Rhino supports much more fluent Arrange-Act-Assert syntax now (with Expect, Stub and Verify methods). More can be found on wiki page here.