Node.js nodejs-测试失败,但正在调用回调
我有一个导出的模块,它有一个方法Node.js nodejs-测试失败,但正在调用回调,node.js,unit-testing,mocha.js,sinon,chai,Node.js,Unit Testing,Mocha.js,Sinon,Chai,我有一个导出的模块,它有一个方法editHeroMage,我正试图使用mocha、chai和sinon对其进行测试。模块有两个作为参数传递的对象,连接和查询。这些是mySql对象,一个包含到数据库的连接,另一个包含在各自模块中定义的查询字符串。我正在导出并尝试测试的expObj是一个“助手”模块 我已经成功地测试了此模块的其他方法,测试方法与我尝试测试此方法的方法相同,但是,当我遇到由于某种原因使用async模块的方法时,我的测试不再按预期进行。我想知道在这个特殊的例子中我是否遗漏了一些东西,因
editHeroMage
,我正试图使用mocha
、chai
和sinon
对其进行测试。模块有两个作为参数传递的对象,连接
和查询
。这些是mySql
对象,一个包含到数据库的连接,另一个包含在各自模块中定义的查询字符串。我正在导出并尝试测试的expObj
是一个“助手”模块
我已经成功地测试了此模块的其他方法,测试方法与我尝试测试此方法的方法相同,但是,当我遇到由于某种原因使用async
模块的方法时,我的测试不再按预期进行。我想知道在这个特殊的例子中我是否遗漏了一些东西,因为我已经测试过同样使用async
的其他模块和方法,并且没有遇到这种行为
当我运行测试时,它会像预期的那样记录“HELLO!”,但是调用了callbackSpy
的断言失败
我在这里发疯了!请帮忙!发生了什么事?测试服之间会有污染吗
试验方法:
expObj.editHeroImage = function(connection, queries, postId, postData, callback) {
async.waterfall([
function(next) {
var qString = queries.getSinglePostById();
connection.query(qString, [postId], function(err, results) {
if (err) {
return next(err);
}
if (!results.length) {
console.log('NO POST FOUND WITH ID ' + postId);
return callback();
}
next(null, results[0].hero_image);
});
},
function(heroImageId, next) {
if (!heroImageId) {
console.log('HERO IMAGE IS NEW - NEXT TICK!');
return next();
}
// Delete resized images of hero image
var queryStr = queries.deleteResizedImages();
var resizedVals = [heroImageId];
connection.query(queryStr, resizedVals, function(err) {
if (err) {
return callback(err);
}
console.log('DELETED RESIZED IMAGES OF HERO IMAGE ' + heroImageId);
var qString = queries.updateHeroImagePath();
var values = [postData.hero_image, heroImageId];
return connection.query(qString, values, function(err, results) {
if (err) {
return next(err);
}
console.log('UPDATED HERO IMAGE ' + heroImageId + ' WITH PATH ' + postData.hero_image);
next('break');
});
});
},
function addHeroImage(next) {
var qString = queries.insertImage();
var values = [postData.hero_image, postId];
connection.query(qString, values, function(err, results) {
if (err) {
return next(err);
}
next(null, results.insertId);
});
},
function addHeroImagePathToPost(heroImageId, next) {
var qString = queries.saveHeroImageId();
var values = [heroImageId, postId];
connection.query(qString, values, function(err) {
if (err) {
return next(err);
}
next();
});
}
], function(err) {
if (err && err !== 'break') {
return callback(err);
}
console.log('HELLO!');
callback(null);
});
};
测试,带有设置:
'use strict';
var chai = require('chai');
var sinonChai = require("sinon-chai");
var proxyquire = require('proxyquire');
var sinon = require('sinon');
chai.use(sinonChai);
var expect = chai.expect;
describe('HELPERS', function() {
var testedModule,
callbackSpy,
fakeConnectionObj,
fakeQueriesObj,
fakePost,
fakeSnakeCaseObj,
queryStub,
connectionStub,
manageStub,
fakeCamelCaseObj;
beforeEach(function() {
fakePost = {};
fakeConnectionObj = {};
fakeQueriesObj = {
getPostIdFromImage: function() {},
insertResizedImages: function() {},
createPost: function() {},
getPostImages: function() {},
getPostsAlternativesImages: function() {},
getSinglePostById: function() {},
getAllImages: function() {},
insertImage: function() {},
deleteMainImage: function() {},
deleteResizedImages: function() {},
updateHeroImagePath: function() {},
saveHeroImageId: function() {}
};
afterEach(function() {
queryStub.resetBehavior();
});
fakeSnakeCaseObj = {
sub_title: '123',
hero_image: '456'
};
fakeCamelCaseObj = {
subTitle: '123',
heroImage: '456'
};
callbackSpy = sinon.spy();
queryStub = sinon.stub();
manageStub = sinon.stub();
connectionStub = {query: queryStub};
testedModule = proxyquire('./../../../../lib/modules/mySql/workers/helpers', {
'./../../../factories/notification-service': {
select: function() {
return {manageSns: manageStub};
}
}
});
});
it('edits hero image', function() {
var _post = {
id: '123',
title: 'vf',
sub_title: 'vf',
slug: 'vf',
reading_time: 4,
created_at: '123',
published_at: '123',
deleted_on: false,
hero_image: 'hero_image_path'
};
var _postId = '123';
queryStub.onCall(0).callsArgWith(2, null, [{hero_image: '55'}]);
queryStub.onCall(1).callsArgWith(2, null);
queryStub.onCall(2).callsArgWith(2, null);
testedModule.editHeroImage(connectionStub, fakeQueriesObj, _postId, _post, function() {
console.log(arguments); // --> {'0': null} as expected
callbackSpy.apply(null, arguments);
});
expect(callbackSpy).has.been.calledWith(null);
});
});
您的断言可能在异步函数返回之前执行 有许多方法可以确保异步函数已完成执行。最干净的方法是以不同的格式设置摩卡测试
describe('...', function () {
var callbackSpy;
before(function () {
var _post = {
id: '123',
title: 'vf',
sub_title: 'vf',
slug: 'vf',
reading_time: 4,
created_at: '123',
published_at: '123',
deleted_on: false,
hero_image: 'hero_image_path'
};
var _postId = '123';
queryStub.onCall(0).callsArgWith(2, null, [{
hero_image: '55'
}]);
queryStub.onCall(1).callsArgWith(2, null);
queryStub.onCall(2).callsArgWith(2, null);
return testedModule.editHeroImage(connectionStub, fakeQueriesObj, _postId, _post, function () {
console.log(arguments); // --> {'0': null} as expected
callbackSpy.apply(null, arguments);
});
});
it('edits hero image', function () {
expect(callbackSpy).has.been.calledWith(null);
});
});
请注意,我已经将您的断言包装在一个descripe块中,这样我们就可以在之前使用。设置存根和执行类的实际逻辑已移动到before
块,并添加了一个返回,这确保了异步函数在转移到断言之前完成
您的其他测试可能已经通过,但它们也会受到影响,这纯粹是一个时间问题 事实上@Varedis认为这是一个时间问题是正确的。然而,使用您的建议,将断言包装在descripe bloack中,并使用before函数设置测试,导致我的存根不再正常工作。然而,考虑到您关于计时的建议,我通过在测试套件中使用done回调成功地解决了这个问题。通过保持设置,我做了一个小小的改变,我的测试突然通过了:
it('edits hero image', function(done) {
var _post = {
id: '123',
title: 'vf',
sub_title: 'vf',
slug: 'vf',
reading_time: 4,
created_at: '123',
published_at: '123',
deleted_on: false,
hero_image: 'hero_image_path'
};
var _postId = '123';
queryStub.onCall(0).callsArgWith(2, null, [{hero_image: '55'}]);
queryStub.onCall(1).callsArgWith(2, null);
queryStub.onCall(2).callsArgWith(2, null);
testedModule.editHeroImage(connectionStub, fakeQueriesObj, _postId, _post, function() {
callbackSpy.apply(null, arguments);
expect(callbackSpy).has.been.calledWith(null);
expect(callbackSpy).has.not.been.calledWith('FDgdjghg');
done();
});
});
事实上,你认为这是一个时间问题是对的。然而,使用您的建议,将断言包装在descripe块中,并使用before函数设置测试,导致我的存根不再正常工作。然而,考虑到您关于计时的建议,我在测试套装中使用done
回调成功地解决了这个问题。