我有一个C#公共API,许多第三方开发人员都使用它来编写自定义应用程序.此外,API被内部开发人员广泛使用.
这个API并没有考虑到可测试性:大多数类方法都不是虚拟的,并且事物没有被分解到接口中.另外,还有一些辅助静态方法.
出于多种原因,我无法在不对使用我的API的程序员开发的应用程序进行重大更改的情况下显着更改设计.但是,我仍然希望使用此API的内部和外部开发人员有机会编写单元测试并能够模拟API中的对象.
有几种方法可以想到,但它们似乎都不是很好:
传统方法是强制开发人员创建一个他们控制的代理类,以便与我的API通信.这在实践中不起作用,因为现在有数百个类,其中许多是有效的强类型数据传输对象,这将很难再现和维护.
强制所有使用想要对其进行单元测试的API的开发人员购买TypeMock.这似乎很苛刻,迫使人们为每个开发人员支付300美元+,并可能要求他们学习不同于他们习惯的模拟对象工具.
浏览整个项目并将所有方法设为虚拟.这将允许使用像Moq或Rhino Mocks这样的免费工具来模拟对象,但它可能会为从未打算从中派生的类带来安全风险.此外,这可能会导致重大变化.
我可以创建一个工具,给定一个输入程序集将输出一个具有相同名称空间,类和成员的程序集,但会使所有方法都是虚拟的,它会使方法体只返回返回类型的默认值.然后,每次我发布API更新时,我都可以发送这个虚拟测试程序集.然后,开发人员可以针对虚拟程序集编写API测试,因为它具有非常可模拟的虚拟成员.这可能有用,但为此编写一个自定义工具似乎有点乏味,我似乎无法找到一个做得好的现有工具(尤其适用于泛型).此外,它的复杂性在于它要求开发人员使用可能会过时的两个不同的程序集.
与#4类似,我可以遍历每个文件并为每个方法和正文添加类似"#ifdef UNITTEST"的内容,以完成与工具相同的操作.这不需要外部工具,但它会用很多丑陋的"#ifdef"来污染代码库.
还有其他我认为不合适的东西吗?像#4中提到的工具是否已经存在?
同样,复杂的因素是这是一个相当大的API(数百个类和~10个文件)并且使用它的现有应用程序使得很难进行剧烈的设计更改.
目前已经 过 几个 问题上堆栈溢出认为是通用性有关改造现有的应用程序,使之可测试的,但似乎没有解决我的(特别是在与众多第三方开发者广泛使用的API的情况下)的关注.我也知道" 有效地使用遗留代码 "并认为它有很好的建议,但我正在寻找一种特定的.net方法,考虑到上面提到的限制.
更新:到目前为止我很欣赏答案.一说帕特里克Hägne长大的是"为什么不能提取接口?" 这确实起到了一定作用,但是存在一些问题,例如现有的设计有很多我们采用暴露具体类的情况.例如:
public class UserRepository { public UserData GetData(string userName) { ... } }
如果给予"IUserData",那么期望具体类(例如"UserData")的现有客户将会中断.
此外,正如评论中所提到的,我们会在某个类中接受一个类,然后为了方便而公开它.如果我们接受一个接口然后不得不将它作为具体类公开,这可能会导致问题.
重大改写或重新设计的最大挑战是对当前的API进行了大量投资(数千小时的开发,可能还有第三方培训).因此,虽然我同意一个更好的SOLID设计重写或抽象层(最终可能成为新的API),专注于接口分离原则等项目,从可测试性的角度来看会是一个加分,但它可能是一个很大的事业,可能目前不能成本合理.
我们确实测试了当前的API,但它是更复杂的集成测试而不是单元测试.
另外,正如Chad Myers所提到的,这个问题解决了.NET框架本身在某些领域面临的类似问题.
我意识到我可能正在寻找一个不存在的"银弹",但所有的帮助都值得赞赏.重要的是保护许多第三方开发人员的巨大时间投资以及创建当前API的巨大现有开发.
所有答案,尤其是那些考虑问题的业务方面的答案,都将得到认真审查.谢谢!