开发者

Mock firing an event from 3rd party class

开发者 https://www.devze.com 2023-03-14 11:15 出处:网络
I\'m trying to write an interaction test that needs to fire an event within a class I do not own (C# 4.0 environment):

I'm trying to write an interaction test that needs to fire an event within a class I do not own (C# 4.0 environment):

public class DoNotOwn
{
  public event EventHandler<SomeEventArgs> SomeEvent;
}

DoNotOwn does does not provide a protected OnSomeEvent to override and does not implement any interfaces or have any virtual members. The class under test has a DoNotOwn instance within it and subscribes to SomeEvent:

public class ClassUnderTest
{
  private DoNotOwn x;

  public SetupDoNotOwn(DoNotOwn arg)
  {
    x = arg;
    x.SomeEvent += MyEventHandler;
  }

  protected void MyEventHandler(object sender, SomeEventArgs args)
  {
    // Does work that needs to be tested
  }
}

I'm aware that I could make a separate method available to the test that 开发者_如何学Pythondoes the inner guts of MyEventHandler, but I'm wondering if there is a way to have a fake DoNotOwn fire that event.

I have RhinoMocks available in the environment. My attempts at raising that event either result in no event firing or a complaint of "Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual ... method)", such as with:

DoNotOwn stub = MockRepository.GenerateStub<DoNotOwn>();
stub.SomeEvent += null;
IEventRaiser eventer = LastCall.GetEventRaiser(); // InvalidOperationException

I'd be willing to try Moq. Typemock not in the budget.


The problem isn't that you don't have "protected OnSomeEvent". That is usually the naming for handling a event, not firing it.

If you didn't understand Chris' answer, he says that you (since you don't have an abstraction "IDoNotOwn" of DoNotOwn) you can instead create a DoNotOwnWrapper that implements a IDoNotOwnWrapper.

interface IDoNotOwnWrapper
{
    event EventHandler<SomeEventArgs> SomeEvent;
}

class DoNotOwnWrapper : IDoNotOwnWrapper
{
    DoNotOwn _internal;
    public DoNotOwnWrapper()
    {
         _internal = new DoNotOwn();
         _internal.SomeEvent += SomeEvent;
    } 
    event EventHandler<SomeEventArgs> SomeEvent;
}

Then you can easily depend on the Wrapper class instead and mock its Abstract interface in the mocking framework.

I would definitely recommend you using Moq because of its crisp syntax, but both RhinoMock and Moq will do the trick.


If you control the class under test, you could wrap the DoNotOwn class and mock the wrapper instead. That would give you some level of control over the interface of the DoNotOwn class as well, in case of changes in the future.


You could also extend the DoNotOwn class which implements an interface defining the event.

public interface IClassDoNotOwn
{
    event EventHandler<SomeEventArgs> SomeEvent;
}

public class ExtendedDonNotOwn : ClassDoNotOwn, IClassDoNotOwn
{

}

And the test method may be :

    [Test]
    private void TestMethod()
    {
        var classDoNotOwn = MockRepository.GenerateStub<IClassDoNotOwn>();
        var classUnderTest = new ClassUnderTest();

        classDoNotOwn.Raise(dno=> dno.SomeEvent += null, this, EventArgs.Empty);
        ......
        ......

    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号