2011-09-28 71 views
4

我有一个使用串行端口与外围设备通信的外设驱动程序。我想单元测试这个驱动程序并试图模拟串口。因此,我创建了框架式的SerialPort的包装把它实现一个接口:如何模拟SerialDataReceivedEventArgs

public interface IScannerPort 
{ 
    Handshake Handshake { get; set; } 
    bool IsOpen { get; } 

    event SerialDataReceivedEventHandler DataReceived; 

    void Close(); 
    void Open(); 
    string ReadLine(); 
} 

现在,我创建了一个使用模拟最小起订量:

Mock<IScannerPort> scannerPort = new Mock<IScannerPort>(); 

然后我想提出的DataReceived事件。但SerialDataReceivedEventArgs不允许我设置EventType属性。所以,我试图嘲笑SerialDataReceivedEventArgs以及,与

Mock<SerialDataReceivedEventArgs> args = new Mock<SerialDataReceivedEventArgs>(); 
args.SetupProperty(a => a.EventType, SerialData.Eof); 

但第二线引发NotSupportedException异常结束了:一个非虚拟(在VB重写)构件上无效设置为:a => a.EventType

如何举办活动?或者我怎样才能嘲笑事件的参数?

回答

7

的SerialDataReceivedEventArgs不一定被嘲笑。人们可以使用反射创建它的一个实例:

ConstructorInfo constructor = typeof (SerialDataReceivedEventArgs).GetConstructor(
    BindingFlags.NonPublic | BindingFlags.Instance, 
    null, 
    new[] {typeof (SerialData)}, 
    null); 

SerialDataReceivedEventArgs eventArgs = 
    (SerialDataReceivedEventArgs)constructor.Invoke(new object[] {SerialData.Eof}); 

则该事件可以用排气孔args来“真正”的实例嘲笑的实例中提出:

scannerPort.Raise(s => s.DataReceived += null, eventArgs); 
3

我想我可能已经部分回答如何提高的情况下,如下解决您的问题:

var mockedScannerPort = new Mock<IScannerPort>(); 

      mockedScannerPort.Setup(sp => sp.ReadLine()) 
          .Returns("123") 
          .Raises(sp => sp.DataReceived += null, new object[] { this, It.IsAny<SerialDataReceivedEventArgs>() }); 

      bool mockEventWasInvoked = false; 
      mockedScannerPort.Object.DataReceived += (sedner, e) => mockEventWasInvoked = true; 
      var retVal = mockedScannerPort.Object.ReadLine(); 

      Assert.AreEqual("123", retVal); 
      Assert.IsTrue(mockEventWasInvoked); 

嘲讽SerialDataReceivedEventArgs是有点棘手,因为它不具有默认构造函数。我会尽快尝试一种解决方法。

编辑:感谢@PVitt提供了对SerialDataEventArgs进行存根的解决方法。为了完整起见,在此发布此信息。

[Test] 
     public void Test() 
     { 
      var mockedScannerPort = new Mock<IScannerPort>(); 

      var constructor = typeof(SerialDataReceivedEventArgs).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(SerialData) }, null); 
      var eventArgs = (SerialDataReceivedEventArgs)constructor.Invoke(new object[] { SerialData.Eof }); 

      mockedScannerPort.Setup(sp => sp.ReadLine()) 
          .Returns("123") 
          .Raises(sp => sp.DataReceived += null, new object[] { this, eventArgs }); 

      bool mockEventWasInvoked = false; 
      SerialDataReceivedEventArgs ea = null; 
      mockedScannerPort.Object.DataReceived += (sedner, e) => 
                 { 
                  mockEventWasInvoked = true; 
                  ea = e; 
                 }; 

      var retVal = mockedScannerPort.Object.ReadLine(); 

      Assert.AreEqual("123", retVal); 
      Assert.IsTrue(mockEventWasInvoked); 
      Assert.IsNotNull(ea); 
      Assert.AreEqual(ea.EventType, SerialData.Eof); 
     } 
+0

感谢您的答复,但我担心关键的一点是错过了。事件处理程序依赖于不能被模拟的SerialDataReceivedEventArgs.EventType(嗯,我希望它可以:)) – PVitt