在这里完成NodeJS测试noob。试图单独测试通过我的API调用的函数(意思是,而不是向特定端点发出http请求,这通常调用多个函数,而这些函数又向不同的第三方API发出请求,我想单独测试函数本身)。它们的调用方式是我为每个数据源(数据源=第三方API)构建了一个类,每个类包含具有相同精确签名的相同函数 - getData
和convertData
,并返回带有结果的回调。
我还创建了一个创建许多user
模拟的模块,因为每个用户上下文都返回不同的数据(意味着,用户对象被输入getData
,其中使用了某些user
属性以确定应返回哪些数据。)
我想测试它的方法是创建多个模拟,然后为每个模拟运行函数。这是我到目前为止所得到的:
// Data sources to iterate over. Each is a class instance acquired through "require".
var dataSources = [
source1,
source2,
source3,
source4
];
describe('getData', function() {
this.timeout(10000);
describe('per data source,', function() {
context('standard call', function() {
// Associative array to hold the data returned, a key for each data source.
var finalResults = {};
// Iterate over all data sources
_.forEach(dataSources, function(dataSource) {
// Generate user mocks
var users = userMocks(10);
// Iterate over all users.
_.forEach(users, function (user) {
// Call each data source with each of the users.
// Numbers of calls to make - (users * data-sources), so in this case - 10*4.
dataSource.getData(user, function (err, data) {
if (err) return done(err);
// Convert the data returned to my format
dataSource.convertData(data, function (err, processedData) {
if (err) return done(err);
// Populate finalResults with converted data from each source
if (finalResults[dataSource.sourceName]) {
finalResults[dataSource.sourceName] = finalResults[dataSource.sourceName].concat(processedData);
} else {
finalResults[dataSource.sourceName] = processedData;
}
});
});
});
});
it('should return something', function(done) {
_.forEach(finalResults.keys, function(key) {
expect(finalResults[key]).to.not.be.empty;
expect(finalResults[key].length).to.be.greaterThan(0);
});
setTimeout(function() {
done();
}, 10000);
})
});
});
});
});`
这是有效的(或者至少测试在查询有效时通过,这是我想要的),但是它很麻烦且(非常)远非优雅或有效,特别是使用超时而不是使用promises,async某种,或者可能是另一种我还不熟悉的替代方案。
由于我发现的大多数资源(http://alanhollis.com/node-js-testing-a-node-js-api-with-mocha-async-and-should/,https://developmentnow.com/2015/02/05/make-your-node-js-api-bulletproof-how-to-test-with-mocha-chai-and-supertest/,https://justinbellamy.com/testing-async-code-with-mocha/(仅举几例)讨论了直接的API测试,而不是特定的异步函数,我很想得到来自更有经验的节点制作者的一些输入/最佳实践技巧。
答案 0 :(得分:0)
您需要知道何时完成一堆异步操作。测试的优雅方法是使用promises和promise聚合:
Promise.all([ promise1, promise2, promise3 ]).then(function(results) {
// all my promises are fulfilled here, and results is an array of results
});
使用bluebird将您的dataSources
包裹到承诺中。您不需要修改自己测试的代码,bluebird提供了方便的方法:
var Promise = require('bluebird')
var dataSources = [
source1,
source2,
source3,
source4
].map(Promise.promisifyAll);
使用新的promisified函数为每个调用创建承诺:
context('standard call', function() {
var finalResults = {};
var promiseOfResults = datasources.map(function(dataSource) {
var users = userMocks(10);
// Promise.all will take an array of promises and return a promise that is fulfilled then all of promises are
return Promise.all( users.map(function(user) {
// *Async functions are generated by bluebird, via Promise.promisifyAll
return dataSource.getDataAsync(user)
.then(dataSource.convertDataAsync)
.then(function(processedData) {
if (finalResults[dataSource.sourceName]) {
finalResults[dataSource.sourceName] = finalResults[dataSource.sourceName].concat(processedData);
} else {
finalResults[dataSource.sourceName] = processedData;
}
});
});
});
// promiseOfResults consists now of array of agregated promises
it('should return something', function(done) {
// Promise.all agregates all od your 'datasource' promises and is fulfilled when all of them are
// You don't need the promise result here, since you agegated finalResults yourself
return Promise.all( promiseOfResults ).then(function() {
_.forEach(finalResults.keys, function(key) {
expect(finalResults[key]).to.not.be.empty;
expect(finalResults[key].length).to.be.greaterThan(0);
});
done();
});
});
除非您需要新的结果集,否则您的其他测试应使用相同的Promise.all( promiseOfResults )
。