在Nodejs中实现unit testing – 意外的失败

无法执行unit testing

问题是testing没有通过,尽pipe当我执行testing时请求和响应数据被添加到数据库。 请提出一些方法来通过这个testing。 预期的状态码200没有在这个testing中发生。 集成testing正在对我的应用程序工作,但我无法debugging此unit testing错误。

//testfile var db = require('../mongodb'), mongoose = require('mongoose'), posts = require('../api/addTodo'), should = require('should'), testUtils = require('./utils'); describe("Add Api", function () { var dummyPost, id; before(function (done) { mongoose.connect('mongodb://localhost:27017/todosdb_test', function() { console.log('Connected To:'+'mongodb://localhost:27017/todosdb_test'); done(); }); dummyPost = new db.Todos({ 'admin': 'Dumm_admin', 'text': 'Dummy', 'completed': true }); dummyPost.save(function (err, post) { if(err) { console.log(err); } id = post._id; }); }); describe("Create Post", function () { it("should create a new todo", function (done) { var req = { body: { 'text': 'Blah blah', 'completed': false }, session: { 'email': 'abc' } }; var res = testUtils.responseValidator(200, function (post) { post.should.have.property('admin'); post.admin.should.equal('abc'); post.should.have.property('text'); post.text.should.equal('Blah blah'); post.should.have.property('completed'); post.completed.should.equal(false); done(); }); console.log(req); console.log(res); posts.add(req, res); }); }); after(function(done){ db.remove({}, function (err) { if(err) {console.log(err);} }); mongoose.disconnect(done); }); }); 
 // utils file var responseValidator = function (expectedStatusCode, validationFunction) { return{ json: function (statusCode, data) { statusCode.should.equal(expectedStatusCode); validationFunction(data); }, send: function (statusCode, data) { statusCode.should.equal(expectedStatusCode); validationFunction(data); } } }; module.exports = { responseValidator } 
  //mongodb file var mongoose = require('mongoose') mongoose.Promise= require('bluebird') var schema1 = new mongoose.Schema({ admin : String, text : String, completed : Boolean }); var schema2 = new mongoose.Schema({ password : String, email: String }); var Todos = mongoose.model('Todos', schema1); var Accounts = mongoose.model('Accounts', schema2); module.exports = { Todos, Accounts } //add api file var db = require('../mongodb'); add = (req, res, next) => { todoRes = { text: req.body.text, completed: req.body.completed } console.log(req.session.email); db.Todos.findOne({ admin: req.session.email, text: todoRes.text }) .then(function (response) { if (!response) { var todo = new db.Todos({ "admin": req.session.email, "text": todoRes.text, "completed": false }); todo.save() .then(function (response) { res.send({ 'status': 'Todo is added' }) }) .catch(function (e) { res.send({ 'status': 'failure', Error: e }); }); } else { res.send({ 'status': 'todo already exist' }); status:'todo already exist'; } }) .catch(function (e) { res.send({ 'status': e }) }) }; module.exports = { add } 

在terminal的错误信息

 > mytodos-app@0.0.0 test /Users/sumitkumarsahu/Desktop/mytodos-app > mocha --recursive ./test/unit.test.js Add Api Connected To:mongodb://localhost:27017/todosdb_test Create Post { body: { text: 'Blah blah', completed: false }, session: { email: 'abc' } } { json: [Function: json], send: [Function: send] } abc Unhandled rejection AssertionError: expected Object { status: Error { operator: 'to be', expected: 200, showDiff: false, actual: Object { status: 'todo already exist' }, stackStartFunction: Function { name: 'assert' }, negate: false, assertion: Assertion { obj: Object { status: 'todo already exist' }, anyOne: false, negate: false, params: Object { operator: 'to be', expected: 200, message: undefined, showDiff: false, actual: Object { status: 'todo already exist' }, stackStartFunction: Function { name: 'assert' }, negate: false, assertion: [Circular] }, onlyThis: undefined, light: false } } } to be 200 at Assertion.fail (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/should/cjs/should.js:258:17) at Assertion.value (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/should/cjs/should.js:335:19) at Object.send (/Users/sumitkumarsahu/Desktop/mytodos-app/test/utils.js:8:31) at /Users/sumitkumarsahu/Desktop/mytodos-app/api/addTodo.js:33:8 at tryCatcher (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/util.js:26:23) at Promise._settlePromiseFromHandler (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/promise.js:507:31) at Promise._settlePromiseAt (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/promise.js:581:18) at Promise._settlePromises (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/promise.js:697:14) at Async._drainQueue (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/async.js:123:16) at Async._drainQueues (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/async.js:133:10) at Immediate.Async.drainQueues (/Users/sumitkumarsahu/Desktop/mytodos-app/node_modules/bluebird/js/main/async.js:15:14) at runCallback (timers.js:672:20) at tryOnImmediate (timers.js:645:5) at processImmediate [as _immediateCallback] (timers.js:617:5) 1) should create a new todo 2) "after all" hook 0 passing (3s) 2 failing 1) Add Api Create Post should create a new todo: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. 2) Add Api "after all" hook: TypeError: db.remove is not a function at Context.<anonymous> (test/unit.test.js:57:20) npm ERR! Test failed. See above for more details. 

在你添加的API文件接口发送:

 res.send({ 'status': 'todo already exist' }); 

但是在你的utils中,你期望看到一个状态码:

 send: function (statusCode, data) { statusCode.should.equal(expectedStatusCode); validationFunction(data); } 

所以“错误”是200 !== { 'status': 'todo already exist' }

然而,你并没有把这些错误扔给testing运行器,所以不是看到testing错误,而是面临超时和未处理的exception。 为了抓住这些,你将需要返回由posts.add创build的posts.add并重新抛出exception。 我也冒昧解决一个潜在的双重捕获问题,并且固定承诺链接以使下一步工作。

 return db.Todos.findOne({ admin: req.session.email, text: todoRes.text }) .then(function (response) { if (!response) { var todo = new db.Todos({ "admin": req.session.email, "text": todoRes.text, "completed": false }); // Need to return here to continue the promise chain!! return todo.save() .then(function (response) { res.send(200, { 'status': 'Todo is added' }) }) .catch(function (e) { res.send({ 'status': 'failure', Error: e }); throw e; }); } else { res.send({ 'status': 'todo already exist' }); status:'todo already exist'; } }, function (e) { // Need to move this error handler here otherwise res.send can be called Twice!!! res.send({ 'status': e }) throw e; }); 

现在我们可以等待testing完成了。 我也会将responseValidator转换为stubs,并将testing切换到基于promise的testing,稍后我会做,但让我们专注于让这个工作….

 var res = testUtils.responseValidator(200, function (post) { post.should.have.property('admin'); post.admin.should.equal('abc'); post.should.have.property('text'); post.text.should.equal('Blah blah'); post.should.have.property('completed'); post.completed.should.equal(false); done(); }); console.log(req); console.log(res); // This is catch any exceptions (like an assertion) and pass it on the test runner posts.add(req, res).catch(done); 

要修复之后,请尝试:

  after(function(done){ db.remove({}, function (err) { if(err) {console.log(err);} mongoose.disconnect(done); }); });