简体   繁体   中英

Mocha tests not failing when they should

I'm trying to test my routes file, and mocha is returning success for all of my expects, even though I've coded a couple that should absolutely fail. I added a 2+2 = 5 test just to make sure something would fail. I have done() in my assertion blocks.

I'm using a MEAN stack, and I tried to test the node files with jasmine, since I'm already using that to test the Angular files, but got tons of crazy errors, so I threw all that out and decided to give mocha a try instead.

Results:

  Routes
    1) makes sure something fails
    GET /
      √ returns status code 200
    GET /nonexistent
      √ returns status code 400
    GET /api/todos
      √ returns status code 200
      √ returns a list of todos

Test file

// test/routes.spec.js

var request   = require('request');
var expect    = require('chai').expect;

describe('Routes', function() {

    var base_url = "http://localhost:8080/"

    // does fail as expected
    it("makes sure something fails", function () {
        expect(2 + 2).to.equal(5);
    });

    describe("GET /", function() {
        it("returns status code 200", function() {
            request(base_url, function(error, response, body) {
                expect(response.statusCode).to.equal(200);
                done();
            });
        });
    });

    //should fail
    describe("GET /nonexistent", function() {
        it("returns status code 400", function () {
            request(base_url + "/nonexistent", function (error, response, body) {
                expect(response.statusCode).to.equal(200);
                done();
            });
        });
    });

    describe("GET /api/todos", function() {
        it("returns status code 200", function() {
            request(base_url + "/api/todos", function(error, response, body) {
                expect(response.statusCode).to.equal(200);
                done();
            });
        });

        //should fail
        it("returns a list of todos", function() {
            request(base_url + "/api/todos", function(error, response, body) {
                console.log(body);
                expect(body).to.equal("abcd");
                done();
            });
        });
    });

});

Routes file:

// app/routes.js

var Todo = require('./models/todo');

module.exports = function(app) {

    // api ---------------------------------------------
    // get all todos
    app.get('/api/todos', function (req, res) {
        Todo.find(function (err, todos) {
            if (err)
                res.send(err)
            res.json(todos);
        });
    });

    // create todo and send back all todos after creation
    app.post('/api/todos', function (req, res) {
        Todo.create({
            text: req.body.text,
            done: false
        }, function (err, todo) {
            if (err)
                res.send(err);

            Todo.find(function (err, todos) {
                if (err)
                    res.send(err)
                res.json(todos);
            });
        });
    });

    // delete a todo
    app.delete('/api/todos/:todo_id', function (req, res) {
        Todo.remove({
            _id: req.params.todo_id
        }, function (err, todo) {
            if (err)
                res.send(err);

            Todo.find(function (err, todos) {
                if (err)
                    res.send(err)
                res.json(todos);
            })
        })
    })

    // application --------------------------------------
    app.get('*', function (req, res) {
        res.sendFile(__dirname + '/public/index.html');
    });
};

You want to use the done callback but none of your tests declare it in the parameters of the callbacks passed to it . Your first test, for instance, should be:

it("returns status code 200", function (done) { // <== Add parameter here!
    request(base_url, function(error, response, body) {
        expect(response.statusCode).to.equal(200);
        done();
    });
});

Without the parameter, Mocha considers the test to be synchronous. So it does not wait for request to call its callback, and ends right away. The fact that done is undefined does not lead to an error because the JavaScript interpreter does not get to done() before Mocha deems the tests over.

I'm a JavaScript novice and had to change my code from

it('getReports', () => {
  getReports()
    .then((res) => {
      assert.equal(200, res.statusCode);
    });
});

to

it('getReports', () => getReports()
  .then((res) => {
    assert.equal(200, res.statusCode);
  }));

ie Had to remove the first set of curly brackets.

After this the Mocha tests reported an error.

Starting with Node 8 you can use the native async/await approach for requests and testing.

First use request-promise or request-promise-native instead request.

const request = require('request-promise-native');

Tests with async/await:

// testing success results - any error will fail the test
it('Returns status code 200', async () => {
    const response = await request(base_url);
    expect(response.statusCode).to.equal(200);
});

// testing for a particular error
it('Testing a particular error is thrown', async () => {
    let error;
    try {
        await request(base_url);
    } catch (err) {
        error = err;
    }
    expect(error).to.be.ok;
    expect(error.message).to.equal('Expected error message');
});

在我的情况下,使用以下命令运行测试文件解决了问题。

node --unhandled-rejections=strict node_modules/.bin/mocha  --require @babel/register --require babel-polyfill test/**/*.test.js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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