【问题标题】:Code from beforeEach running after the 'it'spec在“it”规范之后运行的 beforeEach 代码
【发布时间】:2016-06-20 17:36:41
【问题描述】:

我正在使用 mocha 和 supertest 来测试 REST 服务。在这种情况下,我需要测试 GET 请求后的后续登录是否会返回来自该 GET 请求的查询。

  1. 登录用户
  2. 使用参数对端点执行 GET 请求
  3. 登录用户并期望 GET 请求中的参数作为响应。

由于上述测试将针对各种端点执行多次,这就是我想出的:

/*
 * getRequest.js
 */
'use strict';

var request = require('supertest')
    , verifyUrl = require('./verifyUrl') // verifies basic url formatting
    ;

module.exports = getRequest;

/**
 * Perform GET request using given parameters and call next when finished.
 * @param getEnvironment {json}
 * @param getEnvironment.url {string}
 * @param getEnvironment.endPoint {string}
 * @param getEnvironment.authorization {string}
 * @param next {function} The callback
 */
function(getEnvironment, getParams, next) {
    var url = verifyUrl(getEnvironment.url);
    request(url)
        .get(getEnvironment.endPoint)
        .set("authorization", getEnvironment.authorization)
        .set('Accept', 'application/json')
        .query(getParams)
        .end(next)
}

/*
 * loginWithCallback.js
 * 
 * Performs a basic login but depends on the callback to test the results of the login.
 */
'use strict';

var request = require('supertest')
    , VerifyUrl = require('./VerifyUrl')
    ;

module.exports = LoginWithCallback;

/**
 * Perform basic login, then call next passing in err and res for testing.
 *
 * @param setEnvironment {json}  Expects url and authorization. Any other parameters will be ignored.
 * @param setEnvironment.url {string} The url being tested.
 * @param setEnvironment.authorization {string} 
 * @param next {function} callback function that will perform the actual test.
 */
function LoginWithCallback(setEnvironment, next) {

    var url = VerifyUrl(setEnvironment.url);

    request(url)
        .post('api/users/login')
        .set('authorization', setEnvironment.authorization)
        .set('Accept', 'application/json')
        .end(next);
}

/*
 * e2eTest.js
 */
'use strict';

var base64_encode = require('Base64').btoa
    , should = require('should')
    , jsonValidator = require('is-my-json-valid')
    , mergeJSON = require('lodash/merge')
    , lodashClone = require('lodash/clone')
    , responseSchema = require('./responseSchemas/200.json')
    , login = require('./loginWithCallback')
    , getRequest = require('./getRequest')
    ;

var username = "newUser" + Date.now()
    , password = "passW0rd"
    , testEnvironment = {
        "url": "http://localhost:9000/",
        "endPoint": "api/users/login",
        "authorization": "Basic " + base64_encode(username + ":" + password)
    }
    ;

var expectedResult = {};

describe('End to End testing on' + JSON.stringify(testEnvironment), function () {
    describe('new user, ' + username + ', login', function () {
        it('should return 200 and an empty body message.', function (done) {
            login(testEnvironment, function (err, res) {
                if (err) {
                    done(err);
                }

                res.statusCode.should.deepEqual(200);

                var jsonValidate = jsonValidator(responseSchema, {verbose: true});
                jsonValidate(res.body).should.be.true("Response body failed schema check: \n" +
                    JSON.stringify(jsonValidate.errors, null, 4));

                res.body.should.deepEqual(expectedResult);

                done();
            });
        });
    });


    describe('user, ' + username + ', logs in after performing get request', function () {
        var getRequestParams = {"firstName":"john", "lastName":"doe"};

        beforeEach(function() {
            var getEnviron = lodashClone(testEnvironment);
            getEnviron.endPoint = 'api/persons/findName';
            mergeJSON(expectedResult, {"persons": {"findName": getRequestParams}});
            getRequest(getEnviron, getReqestParams, function(err, res) {
                if (err) {
                    done(err);
                }
                console.log("GET request: " JSON.stringify(res, null, 2));
                done();
            });
        });

        it('should return 200 and query values', function(done) {
             login(testEnvironment, function (err, res) {
             if (err) {
                 done(err)
             }

             console.log("it test: " + JSON.stringify(res, null, 2));

             res.statusCode.should.deepEqual(200);

             var jsonValidate = jsonValidator(responseSchema, {verbose: true});
             jsonValidate(res.body).should.be.true("Response body failed schema check: \n" + JSON.stringify(jsonValidate.errors, null, 4));

             res.body.should.deepEqual(expectedResult);

             done();

        });
    });
});

以上三个文件应该做的事情如下: 1.创建一个新用户 2. 登录新用户并测试其响应是否没有先前的查询参数。 (通过) 3. 执行 GET 请求,然后在 before 块中打印结果 4.在it块中执行用户打印和测试结果的登录。

但我得到的是这样的:

End to End testing on{"url":"http://localhost:9000/","endPoint":"api/users/login","authorization":"Basic bmV3VXNlcjE0NjY0NDI0OTEzNDc6cGFzc1cwcmQ="}
  new user, newUser1466442491347, login
    ✓ should return 200 and an empty body message. (54ms)

  user, newUser1466442491347, logs in after performing persons/findByName request
it test: [res text]
    1) should return and query values
GET request: [res text]

1 passing
1 failing

     Uncaught AssertionError: expected Object {} to equal Object {
  persons: Object { findByName: Object { firstName: 'joe', lastName: 'jones' } }
 }

可以看出,'it' 块似乎在 before 块完成之前运行。根据我对 mocha 的阅读,这不应该发生,因为它在运行“it”块之前等待 before 和 beforeEach 完成。但是,也许 getRequest 的回调在 it 阻塞之后排队?

我做错了什么或误解了什么?

【问题讨论】:

    标签: mocha.js bdd supertest


    【解决方案1】:

    你绝对必须设置你的beforeEach钩子,这样Mocha就知道它是异步的:要么你返回一个承诺给Mocha,要么你使用done回调。要使用done 回调,您必须声明一个采用done 的回调:

    beforeEach(function (done) {
    

    (您可以随意称呼它(例如finished),只要您保持一致(稍后致电finished())。

    【讨论】:

    • 我的问题中的最后一个代码块是否不够? getRequest(getEnvironment, getRequestParams, function(err, res) { done(); }); 但是,意识到我没有正确处理错误,我对其进行了如下修改(不包括res,因为我不使用它):getRequest(getEnvironment, getRequestParams, function(err) { if (err) { done(err); } done(); });(或参见上述问题中的编辑)
    • @Macchtyn 不,这还不够。一方面,正如您自己在这里指出的那样,您没有处理err。一旦事情以正确的顺序执行,很可能会出现错误。另外,好吧,我已经回答了足够多关于 Mocha 的问题,知道有些人真的对应该在哪里声明 done 感到困惑,这是您在问题中没有显示的内容。 (不,真的:有些人忘记声明它,或者在错误的地方声明它。)另外,在getRequest 之后有mergeJSON 是不安全的。不清楚这是否是一个因素,但仍然是。
    • 一旦您编辑问题以使其首先显示应该显示的内容,我很乐意删除此答案。正如我所说,你必须告诉 Mocha 你的钩子是异步的。所以你最初为你的钩子显示的代码(没有done)完全是错误的。即使显示它也没有意义,因为您确实有更好的代码版本:使用done 的版本。您应该编辑问题以准确显示您使用 done 运行的钩子,并解释 当您运行此代码时会发生什么行为。
    • 好的,现在你的编辑问题是你确实没有声明done。我已经编辑了我的答案。
    • 我已编辑问题以在 getRequest 调用中包含改进的代码,并将 mergeJSON 移至 getRequest 之前。不幸的是,我得到了相同的结果。也许,我在其他地方做错了什么。
    猜你喜欢
    • 2013-05-31
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 2017-02-28
    相关资源
    最近更新 更多