重构以减少 Mocha API 测试中的重复
Refactoring to reduce repitition in Mocha API test
当 运行 API 在 Node.js 中进行测试时,我经常发现自己用略有不同的断言重复整个语句块。这似乎是一种浪费,我希望它尊重 DRY 原则。
我们以下面的例子为例:-
const { expect } = require('chai');
const got = require('got');
const core = require('../Libraries/CoreFunctions')
describe('Some description', function() {
beforeEach(function() {
})
it('should do something', function(done) {
got.get('https://someurl.com',
{headers: core.headers()})
.then(res => {
core.respDateCode(res);
console.log(core.prettyJSON(res));
expect(core.something).to.be.lessThan(2000);
done()
})
.catch(err => {
console.log('Error: ', err.message);
});
}).timeout(5000);
it('should do something else', function(done) {
got.get('https://someurl.com',
{headers: core.headers()})
.then(res => {
core.respDateCode(res);
console.log(core.prettyJSON(res));
expect(core.somethingElse).to.be.greaterThan(1000);
done()
})
.catch(err => {
console.log('Error: ', err.message);
});
}).timeout(5000);
});
我正在寻找有关如何最好地重构上述内容以减少重复的建议?
将提取逻辑移动到一个单独的文件中。然后,您可以将每个请求封装到一个函数中(没有参数,因此如果 API URL 发生变化,您的测试将不必更改)。每个测试都应该在“it”块中显式调用被测函数,因此很快就会清楚正在测试的是什么。如果你有很多重复的设置代码,你可以把它移到一个函数中。
隔离 API 调用的一个很好的副作用是,您最终会得到 API 的客户端,它实际上与您的 API.
不要害怕你的测试代码在高层被复制。基本上“给定此设置,当调用被测函数时,就会发生这种情况”。您可以将测试设置放入其他函数中,但不要过度,因为您可能会冒着无法判断在查看测试时实际发生了什么的风险。另外,永远不要抽象掉被测函数。
const { expect } = require('chai');
const gotClient = require('../somewhere/client/uses/got');
const core = require('../Libraries/CoreFunctions')
describe('Some description', function() {
it('should do something', async function(done) {
// given
const res = await gotClient.resource.getOne()
// when
core.functionThatIsBeingTested(res);
// then
expect(core.something).to.be.lessThan(2000);
done()
}).timeout(5000);
it('should do something else', async function(done) {
// given
const res = await gotClient.resource.getOne()
// when
core.functionThatIsBeingTested(res);
// then
console.log(core.prettyJSON(res));
expect(core.somethingElse).to.be.greaterThan(1000);
done()
}).timeout(5000);
});
注意,这个版本和你的版本之间唯一真正的区别是在我的版本中你不需要关心 url 和 headers,这使得代码更可读且更容易理解。如果客户端以它正在获取的 API 命名并且资源是资源的名称,那就更好了。
举个例子:
const res = await twilio.phoneNumbers.availableForPurchase()
当 运行 API 在 Node.js 中进行测试时,我经常发现自己用略有不同的断言重复整个语句块。这似乎是一种浪费,我希望它尊重 DRY 原则。
我们以下面的例子为例:-
const { expect } = require('chai');
const got = require('got');
const core = require('../Libraries/CoreFunctions')
describe('Some description', function() {
beforeEach(function() {
})
it('should do something', function(done) {
got.get('https://someurl.com',
{headers: core.headers()})
.then(res => {
core.respDateCode(res);
console.log(core.prettyJSON(res));
expect(core.something).to.be.lessThan(2000);
done()
})
.catch(err => {
console.log('Error: ', err.message);
});
}).timeout(5000);
it('should do something else', function(done) {
got.get('https://someurl.com',
{headers: core.headers()})
.then(res => {
core.respDateCode(res);
console.log(core.prettyJSON(res));
expect(core.somethingElse).to.be.greaterThan(1000);
done()
})
.catch(err => {
console.log('Error: ', err.message);
});
}).timeout(5000);
});
我正在寻找有关如何最好地重构上述内容以减少重复的建议?
将提取逻辑移动到一个单独的文件中。然后,您可以将每个请求封装到一个函数中(没有参数,因此如果 API URL 发生变化,您的测试将不必更改)。每个测试都应该在“it”块中显式调用被测函数,因此很快就会清楚正在测试的是什么。如果你有很多重复的设置代码,你可以把它移到一个函数中。
隔离 API 调用的一个很好的副作用是,您最终会得到 API 的客户端,它实际上与您的 API.
不要害怕你的测试代码在高层被复制。基本上“给定此设置,当调用被测函数时,就会发生这种情况”。您可以将测试设置放入其他函数中,但不要过度,因为您可能会冒着无法判断在查看测试时实际发生了什么的风险。另外,永远不要抽象掉被测函数。
const { expect } = require('chai');
const gotClient = require('../somewhere/client/uses/got');
const core = require('../Libraries/CoreFunctions')
describe('Some description', function() {
it('should do something', async function(done) {
// given
const res = await gotClient.resource.getOne()
// when
core.functionThatIsBeingTested(res);
// then
expect(core.something).to.be.lessThan(2000);
done()
}).timeout(5000);
it('should do something else', async function(done) {
// given
const res = await gotClient.resource.getOne()
// when
core.functionThatIsBeingTested(res);
// then
console.log(core.prettyJSON(res));
expect(core.somethingElse).to.be.greaterThan(1000);
done()
}).timeout(5000);
});
注意,这个版本和你的版本之间唯一真正的区别是在我的版本中你不需要关心 url 和 headers,这使得代码更可读且更容易理解。如果客户端以它正在获取的 API 命名并且资源是资源的名称,那就更好了。
举个例子:
const res = await twilio.phoneNumbers.availableForPurchase()