|
|
1
102
单元测试应该通过单个方法测试单个代码路径。当一个方法的执行从该方法的外部传递到另一个对象,然后再次返回时,您就有了依赖关系。 当您使用实际的依赖性测试代码路径时,您不是单元测试;而是集成测试。虽然这是好的和必要的,但它不是单元测试。 如果您的依赖是错误的,那么您的测试可能会受到影响,从而返回一个假阳性。例如,您可能会将一个意外的空值传递给依赖项,并且依赖项可能不会像文档中描述的那样将空值传递给它。您的测试没有像应该的那样遇到空参数异常,测试通过了。 此外,您可能会发现,如果不是不可能的话,很难可靠地让依赖对象返回您在测试期间想要的内容。这还包括在测试中抛出预期的异常。 模拟代替了这种依赖。您可以设置对依赖对象调用的期望值,设置执行所需测试时它应该给您的确切返回值,和/或抛出什么异常,以便测试异常处理代码。通过这种方式,您可以轻松地测试有问题的单元。 tl;dr:模拟单元测试涉及的每个依赖项。 |
|
|
2
134
模拟对象在需要时很有用 测试交互 在测试类和特定接口之间。
例如,我们要测试这个方法
使用模拟对象,而不是传递
这在理论上听起来不错,但也有一些缺点。 模拟缺点如果您已经有了一个模拟框架,那么您将倾向于使用模拟对象。 每一次 您需要将接口传递给测试中的类。这样你就完蛋了 即使没有必要也要测试交互 . 不幸的是,对交互进行不必要的(意外的)测试是不好的,因为然后您要测试特定需求是以特定的方式实现的,而不是实现产生了所需的结果。
下面是一个伪代码示例。假设我们已经创建了一个
(在本例中,我们假定我们要测试的不是特定的排序算法,例如快速排序;在这种情况下,后一个测试实际上是有效的。)
在这样一个极端的例子中,很明显为什么后一个例子是错误的。当我们改变
嘲讽模拟框架通常也允许不那么严格的使用,在这种情况下,我们不必精确地指定应该调用多少次方法以及需要什么参数;它们允许创建模拟对象,这些对象用作 stubs .
假设我们有一个方法
在这个例子中,我们并不真正关心
但是当我们改变的时候
另外,测试的可读性也受到了极大的影响,因为我们想写的代码很多,但是我们必须写;不是我们想写的代码。使用模拟对象的测试看起来非常复杂,通常很难阅读。这些测试应该帮助读者理解,如何使用测试下的类,因此它们应该简单明了。如果它们不可读,没有人会维护它们;事实上,删除它们比维护它们容易。 如何解决这个问题?容易地:
总之,模拟对象有其用途,但如果不小心使用, 它们常常鼓励坏的实践、测试实现细节、阻碍重构、产生难以阅读和难以维护的测试。 . 有关mock缺点的更多详细信息,请参见 Mock Objects: Shortcomings and Use Cases . |
|
|
3
44
经验法则: 如果正在测试的函数需要一个复杂的对象作为参数,并且仅仅实例化这个对象(例如,如果它试图建立TCP连接),那么就需要使用模拟。 |
|
|
Ricky Mo · 角度测试如何模拟导入的const 1 年前 |
|
|
Robert · 如何模拟Perl的unlink函数? 1 年前 |
|
|
Ivan · 模拟没有按预期工作(Django) 2 年前 |
|
|
Erfan Sabouri · 在laravel中测试多存储 2 年前 |