我有一个外围驱动程序,它使用串行端口与外围设备通信。我想对这个驱动程序进行单元测试,并试图模拟串口。因此,我为框架类型SerialPort创建了一个包装器,让它实现一个接口:
public interface IScannerPort
{
Handshake Handshake { get; set; }
bool IsOpen { get; }
event SerialDataReceivedEventHandler DataReceived;
void Close( );
void Open( );
string ReadLine( );
}
现在我使用moq创建了一个模拟:
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 =&gt; a.EventType
我如何举办活动?或者我如何模拟事件args?
答案 0 :(得分:9)
不一定要模拟SerialDataReceivedEventArgs。可以使用反射创建它的实例:
ConstructorInfo constructor = typeof (SerialDataReceivedEventArgs).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {typeof (SerialData)},
null);
SerialDataReceivedEventArgs eventArgs =
(SerialDataReceivedEventArgs)constructor.Invoke(new object[] {SerialData.Eof});
然后可以使用vent args的“真实”实例在模拟的实例上引发事件:
scannerPort.Raise( s => s.DataReceived += null, eventArgs );
答案 1 :(得分: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 );
}