【问题标题】:How to mock/stub/shim SerialPort.GetPortNames()如何模拟/存根/填充 SerialPort.GetPortNames()
【发布时间】:2019-10-08 07:34:13
【问题描述】:

我正在尝试在 C# 中测试 ApiController 类,特别是使用 SerialPort.GetPortNames() 的函数。这返回的内容取决于运行它的机器,所以我希望能够以某种方式对其进行填充/存根/模拟以使其返回虚拟数据。

使用 Visual Studio 2015,项目目标为 .net 4.5.2,并使用 Microsoft.VisualStudio.TestTools.UnitTesting

我认为 Microsoft Fakes 可以完全满足我的需要,但我没有 Visual Studio Enterprise。

我了解到 Moq 在这里毫无价值,并且姿势不适用于项目所针对的 .Net 版本 (4.5.2)。

我已经研究过 prig,但除了 datetime.now() 之外,我不知道如何配置它。

而且我不明白如何使用 Smock 进行实际测试。

        [HttpGet]
        [Route("PortList")]
        public HttpResponseMessage SerialPortList()
        {
            HttpResponseMessage response;
            try
            {
                List<string> Ports = new List<string>(SerialPort.GetPortNames());
                response = Request.CreateResponse(HttpStatusCode.OK, Ports);
            }
            catch (Exception ex)
            {
                response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
            }
            return response;
        }

我希望能够填充(正确的词?)来自 SerialPort 的静态方法,并让它返回一个虚拟的串行端口列表(["COM1","COM2"])。

【问题讨论】:

  • Mocking/shim 已经成为一种对大多数用例来说具有可疑利益的宗教。因为您正在测试的代码与真实系统不同,所以您的测试对于报告您的系统在 UAT/PROD 时间的健康程度的贡献为零。在您的情况下,模拟仅在您的计算机没有串行端口时才有用,这不太可能,因为即使您没有说物理 DE-9 插槽,Windows 仍然通过逻辑串行端口表示某些设备(想到 USB)你的主板
  • 我必须使用软件让 USB 在我的机器上显示为串行端口。如果我断开 USB 与另一台设备的连接,我有 0 个串口。
  • USB 物理连接到您的主板,无法移除
  • 我的意思是连接到端口的 USB 插头。 USB 端口不被视为串行端口。我有一个来自奔飞的驱动程序,它带有一个串口到 USB 电缆,当我将另一台机器连接到我的机器(比如我的手机或另一台电脑)时,它显示为我使用 SerialPort.GetPortNames 时调用的串口()。

标签: c# unit-testing mocking serial-port shim


【解决方案1】:

我绕过像SerialPort.GetPortNames 这样模拟静态方法的方法是添加一个间接层。在您的情况下,最简单的方法是创建一个接受 Func&lt;string[]&gt;SerialPortList 重载,就像这样。

public HttpResponseMessage SerialPortList()
{
    return SerialPortList(SerialPort.GetPortNames);
}

public HttpResponseMessage SerialPortList(Func<string[]> getPortNames)
{
    HttpResponseMessage response;
    try
    {
        List<string> Ports = new List<string>(getPortNames());
        response = Request.CreateResponse(HttpStatusCode.OK, Ports);
    }
    catch (Exception ex)
    {
        response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
    }
    return response;
}

在你的单元测试中...

public void Test()
{
    var portNames = new[] { "COM1" };
    foo.SerialPortList(() => portNames);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-14
    • 2016-03-04
    • 2022-01-09
    • 2011-08-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2014-07-14
    相关资源
    最近更新 更多