node.js - 在 Nodejs Express 中实现单元测试 - 意外失败

标签 node.js mongodb unit-testing express mocha.js

无法执行单元测试

问题是测试没有通过,尽管在我执行测试时请求和响应数据已添加到数据库中。请提出一些通过此测试的方法。此测试没有出现预期的状态代码 200。集成测试正在我的应用程序上运行,但我无法调试此单元测试错误。

//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
     }

终端错误信息

> 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 文件中,您与发送接口(interface):

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

但在您的实用程序中您希望看到一个状态代码:

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

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

但是,您并没有将这些错误抛给测试运行器,因此您没有看到测试错误,而是遇到了超时和未处理的异常。为了捕获这些,您需要返回由 posts.add 创建的 promise 并重新抛出异常。我还冒昧地修复了一个潜在的双重捕获问题,并修复了 promise 链以使下一步工作。

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;
    });

现在我们可以等待测试完成。我还会将 responseValidator 转换为 stub 并将测试切换为基于 promise 的测试,我稍后可能会这样做,但让我们专注于让它发挥作用....

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);
        });
    });

关于node.js - 在 Nodejs Express 中实现单元测试 - 意外失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45649534/

相关文章:

unit-testing - Spock 测试框架 : Difference between mock. getProperty ('name' ) vs getName()

c++ - 什么 C++ 设计模式可用于在生产代码和测试代码之间交换函数模板的行为?

javascript - 使用模块的 typescript

node.js - App Engine 上的 React.js 和后端作为服务?

node.js - MongoDB 在数据库中查找一个对象并更新其字段

node.js - 使用 Mongoose 制作验证器的正确方法是什么

node.js - 如何访问 Mongoose 架构属性?

node.js - 使用 nodeclipse 调试 nodeJS 时遇到问题(无法连接到独立 V8 VM)

javascript - for 循环内的变量给出最大值

c# - 当我向 Controller 添加新的依赖项时单元测试中断