如何模拟 SerialDataReceivedEventArgs

发布于 2024-12-06 19:27:14 字数 944 浏览 1 评论 0原文

我有一个外设驱动程序,它使用串行端口与外围设备进行通信。我想对该驱动程序进行单元测试并尝试模拟串行端口。因此,我为框架类型 SerialPort 创建了一个包装器,以使其实现一个接口:

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

But the second line raises a NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: a =>; a.EventType

如何引发事件?或者我如何模拟事件参数?

I have a peripheral driver that uses the serial port to communicate with the peripheral device. I want to unit test this driver and tried to mock the serial port. Therefore I created a wrapper for the framework type SerialPort to have it implement an interface:

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

    event SerialDataReceivedEventHandler DataReceived;

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

Now I created a mock using moq:

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

I then want to raise the DataReceived event. But SerialDataReceivedEventArgs doesn't let me set the EventType property. So I tried to mock SerialDataReceivedEventArgs as well, ending up with

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

But the second line raises a NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: a => a.EventType

How can I raise the event? Or how can I mock the event args?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

好多鱼好多余 2024-12-13 19:27:14

SerialDataReceivedEventArgs 不一定会被模拟。可以使用反射创建它的实例:

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

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

然后可以使用通风参数的“真实”实例在模拟实例上引发事件:

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

The SerialDataReceivedEventArgs doesn't necessarily be mocked. One can create an instance of it using reflection:

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

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

Then the event can be raised on the mocked instance using the "real" instance of the vent args:

scannerPort.Raise( s => s.DataReceived += null, eventArgs );
网名女生简单气质 2024-12-13 19:27:14

我想我可能已经通过回答如何引发事件部分解决了您的问题,如下所示:

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

I think i may have partly solved your problem by answering how to raise the event, as follows:

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

Mocking SerialDataReceivedEventArgs is a bit tricky, since it doesnt have a default constructor. I'll try a workaround shortly.

EDIT: Thanks @PVitt for providing the workaround for stubbing SerialDataEventArgs. Posting this here just for the sake of completeness.

[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 );
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文