2

Does anyone know how I can raise an event on a abstract class?

The test below fails on the last line. The exception I get is the following:

System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).

I am able to raise the event on an interface, but not on an abstract class that implements that interface. This is using the latest build of RhinoMocks (3.6.0.0).

Thanks, Alex

    public abstract class SomeClass : SomeInterface
    {
        public event EventHandler SomeEvent;
    }

    public interface SomeInterface
    {
        event EventHandler SomeEvent;
    }

    [Test]
    public void Test_raising_event()
    {
        var someClass = MockRepository.GenerateMock<SomeClass>();
        var someInterface = MockRepository.GenerateMock<SomeInterface>();

        someInterface.Raise(x => x.SomeEvent += null, someClass, EventArgs.Empty);
        someClass.Raise(x => x.SomeEvent += null, someClass, EventArgs.Empty);
    }
AlexC
  • 1,646
  • 1
  • 14
  • 26
  • What exactly are you trying to unit test? Could you provide the actual code that you want to test? – Darin Dimitrov May 29 '12 at 08:58
  • Darin - I haven't provided actual test code, as it would make it hard to see the forest for the trees. However, for a bit of context, the test target is an adapter class which takes a "SomeClass" in its constructor and implements another interface. I need to test that when the passed "SomeClass" raises an event, the adapter class raises it's own, different event. The adapter class isn't shown in the case above in order to stay focused on the issue, which is that I seem unable to raise an event on a mocked abstract class. – AlexC May 29 '12 at 09:31

1 Answers1

2

Problem is explained by exception message:

System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).

Your event is not virtual, ie. Rhino won't be able to override it. Simply add virtual keyword to your abstract class event definition.

Bit background information. When you call MocksRepository.GenerateMock<SomeClass> Rhino will create dynamic proxy class, which it will use to record calls, prepare stubs and so forth. This class may look +/- like this:

public class SomeClassDynamicProxy1 : SomeClass
{
    public override EventHandler SomeEvent 
    { 
        add { ... }
        remove { ... } 
    }

    ...
}

Without virtual in your SomeClass, this code will naturaly fail as it does now.

k.m
  • 30,794
  • 10
  • 62
  • 86
  • Thanks jimmy_keen. Think I understand the issue now, cheers for the explanation. So I suppose this is a limitation in RhinoMocks for which there is no work around? I'm not a fan of changing the design of the class in order to be able to write tests for it, but if that's what it takes I guess I don't have much choice. – AlexC May 29 '12 at 09:35
  • Are you writing tests *for* the abstract class, or tests for classes which *use* this one? – RJ Lohan May 29 '12 at 09:39
  • @AlexC: That is correct. This is a problem with most (if not all) free frameworks. They use same proxying library, namely [Castle Dynamix Proxy](http://www.castleproject.org/dynamicproxy/index.html) which introduces [this kind of limitations](http://stackoverflow.com/a/9065036/343266). – k.m May 29 '12 at 09:43
  • @RJLohan - The test is for a class which uses the abstract class. I just wanted to show a minimal case which demonstrated the RhinoMocks problem I was trying to solve. – AlexC May 29 '12 at 10:01
  • @jimmy_keen - Thanks for the clarification. Fair enough, can't complain about free mocking frameworks, just didn't realise this was a consideration I'd need to bear in mind. – AlexC May 29 '12 at 10:01