【问题标题】:How do I remove dependencies to 3rd party code when unit testing?单元测试时如何删除对 3rd 方代码的依赖?
【发布时间】:2011-05-04 22:47:35
【问题描述】:

我有一些代码可以执行一些遗留的“数据库”操作,然后处理结果。我想编写一个单元测试来检查调用遗留代码而不与“数据库”交互的方法。

我的代码如下所示:

    public static bool CallRoutine(LegacySession session, /* routine params*/)
    {
        try
        {
            LegacyRoutine routine = session.CreateRoutine(/* routine params */);

            routine.Call();

            // Process result

        }
        catch (LegacyException ex)
        {
            // Perform error handling
        }
    }

如果这是我的全部代码,我将创建 LegacySessionLegacyRoutine 实现的接口,然后编写单元测试,使用这些接口的模拟实现,使用 MOQ 或类似的东西。问题是我无法访问LegacyRoutineLegacySession 的代码,所以我无法让它们实现接口。

关于如何在不过多更改生产代码的情况下做到这一点的任何想法?

【问题讨论】:

  • 你有没有研究过 Moq 之类的模拟库:code.google.com/p/moq
  • @Kane:我打算使用 Moq,但我认为我需要从接口派生为“Moqed”的类才能做到这一点?我无法更改任何一个 Legacy... 类

标签: c# unit-testing nunit dependencies


【解决方案1】:

我建议您使用依赖注入框架。它通过将外部类依赖项分解为注入到类中的对象来帮助您使类更松散地耦合。这些对象通常由一个接口表示,它可以帮助您在生产和测试中使用不同的实现。这样您就不必在测试时实际调用外部数据库。我可以推荐Ninject。这使得依赖注入比手动执行要容易得多。

【讨论】:

    【解决方案2】:

    如果您无法访问 LegacyRoutine(我猜它在引用的 DLL 中),为什么不为其创建一个包装器,然后打开/关闭不同的实现:

    public interface ILegacyWrapper
    {
       ILegacyRoutine CreateRoutine(); 
       // etc etc
    }
    
    public interface ILegacyRoutine
    {
       // put members of LegacyRoutine
    }
    

    知道我的意思吗?只需将所有内容模拟到包装器/接口中即可。

    那么你可以去:

    ILegacyRoutine routine = session.CreateRoutine(/* routine params */)
    

    session 将被声明为 ILegacyWrapper,但使用模拟混凝土实现。

    另外,不言而喻(但我还是会这么说),您应该考虑使用 DI 框架来让您的生活更简单。否则你会以IFoo foo = new Foo()(硬编码注入)结束。

    StructureMap 是我选择的 DI 毒药。

    HTH

    【讨论】:

    • 我想这是要走的路 - 在会话周围创建一个包装器,我希望会有一些狡猾的技巧来避免需要创建一组全新的包装器类作为这些东西在很多地方都使用过,它们都需要手动更改。
    • 这就是你使用依赖注入的原因。这样您只需要更改 1 个地方(注册表)。如果您找到更好的选择,请告诉我,但这是我能看到的唯一方法。
    【解决方案3】:

    搜索 C# 模拟具体类型。抱歉,我必须运行,但这是我发现的第一个可以解决您的问题的链接(可能有更好的解决方案,但看起来还可以):

    http://docs.typemock.com/isolator/##typemock.chm/Documentation/CreatingFakesWithAAA.html

    另外,请查看起订量,我在过去取得了巨大的成功

    【讨论】:

      【解决方案4】:

      您可以在他们的 API 上编写一个瘦包装器,您确实有一个接口。这是否可行取决于 API 的大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-10
        • 2014-01-27
        相关资源
        最近更新 更多