如何模拟SerialDataReceivedEventArgs
问题描述:
我有一个使用串行端口与外围设备通信的外设驱动程序。我想单元测试这个驱动程序并试图模拟串口。因此,我创建了框架式的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
如何举办活动?或者我怎样才能嘲笑事件的参数?
答
的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);
答
我想我可能已经部分回答如何提高的情况下,如下解决您的问题:
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);
}
感谢您的答复,但我担心关键的一点是错过了。事件处理程序依赖于不能被模拟的SerialDataReceivedEventArgs.EventType(嗯,我希望它可以:)) – PVitt