我正在尝试编写一个需要在我不拥有的类中触发事件的交互测试(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不在预算范围内。
答案 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);
......
......
}