c# - 模拟 COM 对象

标签 c# unit-testing com moq mocking

我一直在为只能获取和返回字符串的 COM 对象开发一个包装器。 COM 对象的接口(interface)如下所示:

    interface IMapinfo
    {
        void Do(string cmd);
        string Eval(string cmd);
    }

现在我已经创建了包含基本函数的类,如下所示:

    public class Table 
    {
        IMapinfo MI;
        public string Name
        {
            //pass the command to the COM object and get back the name.
            get{return MI.Eval("TableInfo(1,1")");}
        }

    }

现在我想对这些类进行单元测试,而不必每次都创建真正的 COM 对象,设置世界然后运行测试。所以我一直在研究使用模拟对象,但我对在这种情况下如何使用模拟有点困惑。

我计划使用 Moq,所以我编写了这样的测试:

        [Test]
        public void MockMapinfo()
        {
            Moq.Mock<Table> MockTable = new Moq.Mock<Table>();
            MockTable.ExpectGet(n => n.Name)
                .Returns("Water_Mains");

            Table table = MockTable.Object;
            var tablename = table.Name;

            Assert.AreEqual("Water_Mains", tablename,string.Format("tablename is {0}",tablename));
            Table d = new Table();
         }

这是模拟 COM 对象的正确方法吗?如何验证发送到 eval 函数的字符串是否正确?还是我做错了?

最佳答案

这是重复的吗? How would I do TDD with a COM OLE object

编辑:看起来您在问同样的问题,但为了验证您的模拟代码(OOPS)。

你还没有完全适应你的模拟场景。您想要隔离外部依赖关系是正确的,并且您的 COM 对象肯定满足该标准。虽然我不是一个最小起订量的人(我更喜欢 RhinoMocks),但模拟背后的想法是交互测试...

交互测试是关于内聚的对象集如何协同工作的。这种情况下的有效测试是为依赖于 COM 对象行为的组件编写测试。

在这种情况下,您的“表”就像 COM 对象的包装器一样,也依赖于 COM 对象的行为。为了便于论证,假设您的 Table 对象针对从 COM 对象返回的值执行自定义逻辑。

现在,您可以为 Table 对象编写独立的测试,同时使用 Mocks 模拟 COM 对象的行为。

public class Table
{
   public Table(IMapInfo map)
   {
      _map = map;
   }

   public string Name
   {
      get 
      {
        string value = _map.Eval("myexpression");
        if (String.IsNullOrEmpty(value))
        {
            value = "none";
        }
        return value;
      }
   }

   private IMapInfo _map;
}

[TestFixture]
public class TableFixture // is this a pun?
{
   [Test]
   public void CanHandleNullsFromCOM()
   {
       MockRepository mocks = new MockRepository(); // rhino mocks, btw
       IMapInfo map = mocks.CreateMock<IMapInfo>();

       using (mocks.Record())
       {
          Expect.Call(map.Eval("myexpression").Return(null);
       }

       using (mocks.PlayBack())
       {
          Table table = new Table(map);
          Assert.AreEqual("none", table.Name, "We didn't handle nulls correctly.");
       }

       mocks.verify();
   }
}

也许您的 COM 对象在调用时会抛出异常,或者它可能不能很好地处理字符串表达式。我们实际上是在测试 Table 对象如何与 IMapInfo 交互,而不依赖于 COM 对象的实现。我们还在 Table 和 IMapInfo 之间强制建立关系,因为在测试期间必须调用 IMapInfo 对象。

希望这有帮助。

关于c# - 模拟 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/304435/

相关文章:

c# - WPF 数据网格中的内存泄漏问题

java - JUnit 4.xx (Java) 尝试获取行覆盖范围时出现 Mockito 问题

c# - 当只需要几个方法时,有什么方法可以避免创建巨大的 C# COM 接口(interface)包装器?

c# - 将数据库上下文移动到 DAL 类库后的 .Net Core 2.0 Web Api 循环依赖

c# - 尝试在 C# 中使用 DotLiquid

c# - 在 PROD 环境下使用 Redis Win64 端口

Python - 为具有上下文管理器的类方法创建模拟测试

python - 有人有使用 Python Zeep 和 Mock 对 SOAP API 进行单元测试的示例吗?

c# - 来自 C++ COM 的 C# 字符串

com - IClassFactory::LockServer 的意义何在?