2011-06-19 48 views
0

我想写需要火的类内的事件我没有(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。键入锁定不在预算中。

回答

1

问题不在于您没有“受保护的OnSomeEvent”。那通常命名为处理一个事件,而不是射击它。

如果你不明白克里斯的回答,他说你(因为你没有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; 
} 

然后你就可以很容易地依赖于包装类,而不是和讥笑它抽象接口的模拟框架。

我肯定会推荐你使用Moq,因为它的语法很简洁,但是RhinoMock和Moq都会这样做。

+0

我会不同意OnSomeEvent用于处理。在引发事件的类中定义时,它是允许派生类也提高事件的典型模式。 来自框架设计指南: “对于每个事件,包含引发事件的相应受保护虚拟方法......按照惯例,方法的名称应以”On“开头,后面紧跟事件名称。 “ 前缀On可能不是最好的用法,但那是惯例。 否则我同意你的答案。在这堂课中适应我所需要的一切都是一项工作,但它会做。 – Sentinel

0

如果你控制着被测试的类,你可以包装DoNotOwn类并且模拟包装。如果将来发生变化,那么这会让您对DoNotOwn类的界面有一定程度的控制。

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); 
     ...... 
     ...... 

    }