简体   繁体   English

在Node.js Express中实施单元测试-意外失败

[英]Implementing unit testing in Nodejs express - unexpected failure

Unable to perform unit testing 无法执行单元测试

The problem is that the test is not passing, although the request and response data is added to the database when I perform the test. 问题是尽管我在执行测试时将请求和响应数据添加到了数据库,但测试未通过。 Kindly suggest some way to pass this test. 请提出一些通过此测试的方法。 The expected status code 200 is not happening with this test. 此测试未发生预期的状态代码200。 The integration test is working on my app but i am unable to debug this unit testing error. 集成测试正在我的应用程序上进行,但是我无法调试此单元测试错误。

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

Error message at 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.

In your add api file you interface with send: 在您的添加api文件中,您可以使用send接口:

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

but in your utils you expect to see a status code: 但是您希望在utils中看到状态码:

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

So the "error" is that 200 !== { 'status': 'todo already exist' } 因此,“错误”是200 !== { 'status': 'todo already exist' }

However, you are not throwing these errors to the test runner so instead of seeing the test error you are confronted with a timeout and the unhandled exception. 但是,您不会将这些错误抛出给测试运行程序,因此,您会看到超时和未处理的异常,而不是看到测试错误。 In order to catch these you will need to return the promise created by posts.add and rethrow exceptions. 为了抓住这些,您将需要返回由posts.add创建的posts.add并重新抛出异常。 I also took the liberty of fixing a potential double catch issue as well as fixed the promise chaining to make the next step work. 我还自由地解决了潜在的双重捕获问题,并修复了诺言链以使下一步可行。

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

Now we can wait for the test to finish. 现在我们可以等待测试完成。 I would also convert responseValidator to just be stubs and switch test to a promise based test, and I may do that later but let's focus on getting this to work.... 我还会将responseValidator转换为存根,然后将测试切换到基于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);

To fix the after, try: 要解决此问题,请尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM