tdd - 为第 3 方代码创建测试
tdd - creating tests for 3rd party code
如果我要测试的方法或过程依赖于来自第 3 方的一段代码,我该如何创建单元测试?比如说,我有一个使用来自第三方来源的 类 的方法,该方法需要只能在功能测试中完成的设置。我应该如何处理这个问题?很多时候,第三方依赖是不能mock的,但是我的方法确实需要用到。
此外,我是否应该避免单元测试甚至功能测试利用实际数据?比如,我的测试不应该连接到数据库 API 以临时添加数据、对其进行操作和测试,然后再删除它吗?
一般来说,假设第 3 方软件已经过测试并且可以正常工作。虽然当你发现一个错误时它会让你大吃一惊。
这取决于您要对什么进行单元测试。有些事情,例如访问一些奇特的硬件或资源,或者简单的网络连接,不应该进行单元测试。对于此类调用,我们使用模拟,不对其进行单元测试。
对于数据库,您可以使用模拟而不是真实的 类 来访问数据库。或者,您可以在单元测试设置方法中在内存中创建数据库,并在清理时销毁它们。
单元测试
你应该测试一切。但不是所有的东西都使用单元测试。单元测试不依赖于环境——数据库、互联网连接等。使用 untrusted/unstable 第 3 方工具的最佳实践是在您的代码和第 3 方代码之间创建反腐败层。所以重构你的代码,让你的业务逻辑尽可能独立。并对业务逻辑进行单元测试。
如果您不确定第 3 方代码的工作原理或将来是否会更改,您可以 'learning tests'。这些是断言您所依赖的行为的单元测试(如果可能的话)。在学习测试中,你只测试第 3 方代码,而不是你的
如果第 3 方代码不太受信任(众所周知的开源库),那么您假设它有效,不要进行任何分离,并且您只对您的代码而不是库进行单元测试。
非单元测试
如果您的测试需要外部环境(数据库、网络等),那么您应该进行集成测试。它的目的不是测试业务逻辑,而是测试您是否正确连接了所有部分。 sql 测试是最著名的异常之一。
没有关于如何进行集成测试的简单规则(您可以编写有关 sql 测试的书籍)。这取决于你到底想测试什么,你与你的生产环境有多少相似性need/want。例如,您可以对内存数据库或类似生产的数据库(oracle、postgres 等)进行 sql 测试。无论您如何设计集成测试,您都必须确保每个测试都以已知的环境状态开始。并且您已经考虑了使环境处于肮脏状态的错误以及此类测试的速度
你说:
Most of the time, the third party dependency can't be mocked
为什么?您始终可以为与第 3 方组件的交互定义一个接口,然后提供一个简单地将每次调用委托给第 3 方组件的实现,然后您就可以为您的测试提供该接口的模拟。
如果第 3 方组件有很大的 API,这可能会做很多工作,但它可能仍然值得做。
存在用于围绕 .net 文件系统创建包装器的类似 projects 类,以便您可以编写不依赖文件系统的测试。
所以你可以这样做:
public interface IMyDependency
{
public void SomeMethod();
public int CaclateSomething();
//add other methods that you will call in the 3rd party dependency
}
然后有一个包装器,它只委托给您正在使用的实际第 3 方组件,如下所示:
public class MyDependencyWrapper : IMyDependency
{
private My3rdPartyDepency actualDependency;
public MyDependencyWrapper(My3rdPartyDepency actualDependency)
{
this.actualDependency=actualDependency;
}
public void SomeMethod()
{
actualDependency.SomeMethod()l
}
public int CaclateSomething(string aParam)
{
return actualDependency.CalculateSomething(aParam);
}
//add other methods that you will call in the 3rd party dependency
}
现在有了这个,您可以在测试中只使用接口,因此可以编写单元测试而不依赖于实际的第 3 方组件。
如果我要测试的方法或过程依赖于来自第 3 方的一段代码,我该如何创建单元测试?比如说,我有一个使用来自第三方来源的 类 的方法,该方法需要只能在功能测试中完成的设置。我应该如何处理这个问题?很多时候,第三方依赖是不能mock的,但是我的方法确实需要用到。
此外,我是否应该避免单元测试甚至功能测试利用实际数据?比如,我的测试不应该连接到数据库 API 以临时添加数据、对其进行操作和测试,然后再删除它吗?
一般来说,假设第 3 方软件已经过测试并且可以正常工作。虽然当你发现一个错误时它会让你大吃一惊。
这取决于您要对什么进行单元测试。有些事情,例如访问一些奇特的硬件或资源,或者简单的网络连接,不应该进行单元测试。对于此类调用,我们使用模拟,不对其进行单元测试。
对于数据库,您可以使用模拟而不是真实的 类 来访问数据库。或者,您可以在单元测试设置方法中在内存中创建数据库,并在清理时销毁它们。
单元测试
你应该测试一切。但不是所有的东西都使用单元测试。单元测试不依赖于环境——数据库、互联网连接等。使用 untrusted/unstable 第 3 方工具的最佳实践是在您的代码和第 3 方代码之间创建反腐败层。所以重构你的代码,让你的业务逻辑尽可能独立。并对业务逻辑进行单元测试。
如果您不确定第 3 方代码的工作原理或将来是否会更改,您可以 'learning tests'。这些是断言您所依赖的行为的单元测试(如果可能的话)。在学习测试中,你只测试第 3 方代码,而不是你的
如果第 3 方代码不太受信任(众所周知的开源库),那么您假设它有效,不要进行任何分离,并且您只对您的代码而不是库进行单元测试。
非单元测试
如果您的测试需要外部环境(数据库、网络等),那么您应该进行集成测试。它的目的不是测试业务逻辑,而是测试您是否正确连接了所有部分。 sql 测试是最著名的异常之一。
没有关于如何进行集成测试的简单规则(您可以编写有关 sql 测试的书籍)。这取决于你到底想测试什么,你与你的生产环境有多少相似性need/want。例如,您可以对内存数据库或类似生产的数据库(oracle、postgres 等)进行 sql 测试。无论您如何设计集成测试,您都必须确保每个测试都以已知的环境状态开始。并且您已经考虑了使环境处于肮脏状态的错误以及此类测试的速度
你说:
Most of the time, the third party dependency can't be mocked
为什么?您始终可以为与第 3 方组件的交互定义一个接口,然后提供一个简单地将每次调用委托给第 3 方组件的实现,然后您就可以为您的测试提供该接口的模拟。
如果第 3 方组件有很大的 API,这可能会做很多工作,但它可能仍然值得做。
存在用于围绕 .net 文件系统创建包装器的类似 projects 类,以便您可以编写不依赖文件系统的测试。
所以你可以这样做:
public interface IMyDependency
{
public void SomeMethod();
public int CaclateSomething();
//add other methods that you will call in the 3rd party dependency
}
然后有一个包装器,它只委托给您正在使用的实际第 3 方组件,如下所示:
public class MyDependencyWrapper : IMyDependency
{
private My3rdPartyDepency actualDependency;
public MyDependencyWrapper(My3rdPartyDepency actualDependency)
{
this.actualDependency=actualDependency;
}
public void SomeMethod()
{
actualDependency.SomeMethod()l
}
public int CaclateSomething(string aParam)
{
return actualDependency.CalculateSomething(aParam);
}
//add other methods that you will call in the 3rd party dependency
}
现在有了这个,您可以在测试中只使用接口,因此可以编写单元测试而不依赖于实际的第 3 方组件。