Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使现有的公共API可供使用它的外部程序员测试?_C#_.net_Unit Testing - Fatal编程技术网

C# 如何使现有的公共API可供使用它的外部程序员测试?

C# 如何使现有的公共API可供使用它的外部程序员测试?,c#,.net,unit-testing,C#,.net,Unit Testing,我有一个C#公共API,许多第三方开发人员使用它,他们在上面编写了自定义应用程序。此外,API被内部开发人员广泛使用 编写此API时并没有考虑可测试性:大多数类方法都不是虚拟的,并且没有考虑到接口中的因素。此外,还有一些辅助静态方法 由于许多原因,我无法在不导致使用我的API的程序员开发的应用程序发生重大更改的情况下显著更改设计。但是,我仍然希望给使用此API的内部和外部开发人员机会编写单元测试,并能够模拟API中的对象 我想到了几种方法,但没有一种是好的: 传统的方法是强制开发人员创建一个他们

我有一个C#公共API,许多第三方开发人员使用它,他们在上面编写了自定义应用程序。此外,API被内部开发人员广泛使用

编写此API时并没有考虑可测试性:大多数类方法都不是虚拟的,并且没有考虑到接口中的因素。此外,还有一些辅助静态方法

由于许多原因,我无法在不导致使用我的API的程序员开发的应用程序发生重大更改的情况下显著更改设计。但是,我仍然希望给使用此API的内部和外部开发人员机会编写单元测试,并能够模拟API中的对象

我想到了几种方法,但没有一种是好的:

  • 传统的方法是强制开发人员创建一个他们控制的代理类,该类将与我的API通信。这在实践中是行不通的,因为现在有数百个类,其中许多都是有效的强类型数据传输对象,复制和维护起来很困难

  • 强制所有使用API并希望对其进行单元测试的开发人员购买。这似乎很苛刻,迫使人们为每个开发者支付300美元以上的费用,并可能要求他们学习一种不同于过去的模拟对象工具

  • 检查整个项目,并使所有方法虚拟化。这将允许使用诸如或之类的免费工具模拟对象,但它可能会为从未打算从中派生的类带来安全风险。此外,这可能会导致中断更改

  • 我可以创建一个工具,在给定输入程序集的情况下,该工具将输出具有相同名称空间、类和成员的程序集,但会使所有方法都是虚拟的,并使方法体只返回返回返回类型的默认值。然后,每次发布API更新时,我都可以发布这个虚拟测试组件。然后,开发人员可以针对虚拟程序集编写API测试,因为虚拟程序集具有非常可模拟的虚拟成员。这可能行得通,但是为它编写一个自定义工具似乎有点乏味,而且我似乎找不到一个现有的工具可以很好地完成它(尤其是与泛型一起工作的工具)。此外,它还需要开发人员使用两个可能过时的不同程序集

  • 与#4类似,我可以遍历每个文件,在每个方法和主体中添加类似于“#ifdef UNITTEST”的内容,以完成与工具相同的功能。这不需要外部工具,但它会用许多丑陋的“ifdef”污染代码库

  • 还有什么我认为不合适的吗?我在#4中提到的工具已经存在了吗

    同样,复杂的因素是,这是一个相当大的API(数百个类和~10个文件),并且现有的应用程序都在使用它,这使得很难进行剧烈的设计更改

    在对现有应用程序进行改造以使其可测试方面,存在一些关于堆栈溢出的通用问题,但似乎没有一个解决我所关心的问题(特别是在许多第三方开发人员广泛使用API的情况下)。我也知道“”并认为它有很好的建议,但鉴于上述限制,我正在寻找一种特定的.net方法

    更新:我非常感谢目前为止的答案。提出的一个问题是“为什么不提取接口?”这在一定程度上确实有效,但也存在一些问题,比如现有的设计在很多情况下会暴露一个具体的类。例如:

    public class UserRepository 
    { 
        public UserData GetData(string userName) 
        {
            ...
        } 
    }
    
    如果为期望使用具体类(例如“UserData”)的现有客户提供了“IUserData”,则这些客户将中断

    此外,正如在评论中提到的,在某些情况下,我们引入一个类,然后为了方便起见将其公开。如果我们接受了一个接口,然后不得不将其作为一个具体的类公开,这可能会导致问题

    重大重写或重新设计的最大挑战是当前API有巨大的投资(数千小时的开发,可能与第三方培训一样多)。因此,虽然我同意,从可测试性的角度来看,一个更好的设计重写或抽象层(最终可能成为新的API)将是一个加号,但这将是一个很大的任务,目前可能无法证明成本是合理的

    我们确实有针对当前API的测试,但它是更复杂的集成测试,而不是单元测试

    此外,正如所提到的,这个问题解决了.NET框架本身在某些领域面临的类似问题

    我意识到我可能正在寻找一个不存在的“银弹”,但所有的帮助都很感激。重要的部分是保护许多第三方开发人员投入的大量时间,以及创建当前API的大量现有开发


    所有的答案,特别是那些考虑问题的商业方面的答案,都会被仔细地审查。谢谢

    您没有提到的一种方法(在大多数情况下我更喜欢这种方法)是为您希望API用户能够伪造的类提取接口。不知道您的API并不是每个类都必须提取接口。

    第三方用户不应该测试您的API。他们希望根据您的API测试他们的代码,因此他们需要创建API的模拟等,但他们将依靠您对API的测试来确保其工作。或者这就是你的意思?您想让您的API易于测试吗


    在这种情况下重新开始,这次考虑测试人员:)

    另一种方法是创建一个单独的API分支,并在那里执行选项3。那你呢
    public interface IUserRepository
    {
        IUserData GetData(string userName);
    }
    
    public class UserRepository 
        : IUserRepository
    {
        // The old method is not touched.
        public UserData GetData(string userName)
        {
            ...    
        }
    
        // Explicitly implement the interface method.
        IUserData IUserRepository.GetData(string userName)
        {
            return this.GetData(userName);
        }
    }