【问题标题】:Mocking a COM object模拟 COM 对象
【发布时间】:2008-11-20 14:47:28
【问题描述】:

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

    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 对象,设置世界然后运行测试。所以我一直在研究使用模拟对象,但我对如何在这种情况下使用模拟有点困惑。

我打算使用起订量,所以我这样写了这个测试:

        [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 函数的字符串如何正确?还是我做错了?

【问题讨论】:

    标签: c# unit-testing com moq mocking


    【解决方案1】:

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

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

    你并不完全适合你的模拟场景。您希望隔离外部依赖项是正确的,并且您的 COM 对象肯定符合该标准。虽然我不是 moq 的人(我更喜欢 RhinoMocks),但 mock 背后的想法是 交互测试......

    交互测试是关于对象集合如何协同工作的。在这种情况下,一个有效的测试是为依赖于 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 对象。

    希望这会有所帮助。

    【讨论】:

    • Soft of is,但当时我只是使用直接的 COM 对象将字符串传递给,现在我有一堆层,字符串可以通过,如果这有任何意义的话。
    • 而这次我更多的是寻找“这是否正确”而不是“我是否应该使用模拟”类型的问题
    • 我已经更新了我的答案。你的例子是错误的;您断言模拟框架为您提供了您提供的价值,这将始终通过。我的示例展示了如何测试 Table 和 IMapInfo 之间的交互。
    • 如果您正在测试与 Table 交互的对象,您的示例将是正确的。但是简单地创建一个模拟然后断言模拟具有你给它的值不是一个有效的测试。
    猜你喜欢
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多