模拟从第三方课程中解雇一个事件

时间:2011-06-19 18:49:00

标签: c# unit-testing rhino-mocks

我正在尝试编写一个需要在我不拥有的类中触发事件的交互测试(C#4.0环境):

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

DoNotOwn不会提供受保护的OnSomeEvent来覆盖,也不会实现任何接口或拥有任何虚拟成员。被测试的类中有一个DoNotOwn实例,并订阅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
  }
}

我知道我可以为MyEventHandler的内部测试做一个单独的方法,但是我想知道是否有办法让假的DoNotOwn触发该事件。

我在环境中使用RhinoMocks。我提出该事件的尝试要么导致没有事件触发,要么投诉“无效呼叫,最后一次呼叫已被使用或未进行任何呼叫(确保您正在呼叫虚拟...方法)”,例如用:

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

我愿意尝试Moq。 Typemock不在预算范围内。

3 个答案:

答案 0 :(得分:1)

问题不在于您没有“受保护的OnSomeEvent”。这通常是处理事件的命名,而不是解雇

如果你不理解Chris的回答,他说你(因为你没有DoNotOwn的抽象“IDoNotOwn”)你可以创建一个实现IDoNotOwnWrapper的DoNotOwnWrapper。

interface IDoNotOwnWrapper
{
    event EventHandler<SomeEventArgs> SomeEvent;
}

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

然后您可以轻松地依赖Wrapper类并在模拟框架中模拟其Abstract接口。

我肯定会推荐你使用Moq,因为它的语法清晰,但RhinoMock和Moq都可以解决这个问题。

答案 1 :(得分:0)

如果你控制被测试的类,你可以包装DoNotOwn类并改为模拟包装器。如果将来发生变化,这将使您对DoNotOwn类的接口有一定程度的控制。

答案 2 :(得分:0)

您还可以扩展DoNotOwn类,该类实现定义事件的接口。

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

public class ExtendedDonNotOwn : ClassDoNotOwn, IClassDoNotOwn
{

}

测试方法可能是:

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

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

    }