Unit testing 模拟和单元测试实现依赖项

Unit testing 模拟和单元测试实现依赖项,unit-testing,mocking,Unit Testing,Mocking,我正试图对单元测试的实践有所了解。我已经读到单元测试不应该依赖于实现 我理解这一点的方式是,例如,如果我们有一个函数intaddtworumbers(inta,intb),我们应该测试,例如加法是否返回正确的结果(即addtworumbers(2,2)==4),我们不应该关心,addtwownumbers只调用一次operator+,也可以使用位操作 这对我来说似乎是合理的,而且——在我看来——在测试和代码之间提供了一个相当好的解耦 进入模拟框架。就我阅读他们的文档所知,他们的功能相当于 (a)

我正试图对单元测试的实践有所了解。我已经读到单元测试不应该依赖于实现

我理解这一点的方式是,例如,如果我们有一个函数
intaddtworumbers(inta,intb)
,我们应该测试,例如加法是否返回正确的结果(即
addtworumbers(2,2)==4)
,我们不应该关心,
addtwownumbers
只调用一次
operator+
,也可以使用位操作

这对我来说似乎是合理的,而且——在我看来——在测试和代码之间提供了一个相当好的解耦

进入模拟框架。就我阅读他们的文档所知,他们的功能相当于

(a) 生成实现基类(stubing)和

(b) 检查是否根据测试人员设定的期望调用了该功能

我对(a)没有问题-我理解我们有时需要为测试硬编码一些外部依赖项的功能。但是我不明白,为什么我们要检查测试代码是否以测试人员期望的方式调用了mock的功能

难道我们不应该只关心被测试的方法返回什么或者它如何修改它的out参数,而不真正关心它的实现细节吗?模拟框架的验证功能是否不会在测试代码和测试代码之间引入紧密耦合

但是我不明白,为什么我们要检查测试代码是否以测试人员期望的方式调用了mock的功能

因为方法的契约并不总是返回某些内容或修改其参数。有时,该方法的契约(或包含)会产生副作用。以以下方法为例:

void notifyServerOfError(error: string) {
    this.http.post('/api/errors', {
        error: error,
        ip: myIpAddress
    });
}
此方法不返回任何内容。它不修改其参数。它的唯一职责是将包含特定细节的特定对象发送到特定URL。因此,单元测试这种方法应该验证合同是否得到遵守

这样做的一个好方法是模拟
http
依赖关系,并检查在调用此方法时,是否确实使用正确的URL和正确的数据调用了其
post()
方法