Mocha- 使用全局中间件测试 Express API

Mocha- Testing Express API With Global Middleware

这是我的第一个 Express 应用程序,我在为端点编写测试时遇到了一些问题。

目前我没有使用数据库来存储令牌或在登录时检查用户。

我写的测试通过了,但是还不完整。例如,我将如何测试已正确验证的用户?

我将如何模拟身份验证过程?

因为我已经创建了一个全局中间件函数和 checkLoging 函数如何将这些因素纳入我的测试?

如何测试身份验证和路由?

这是我的代码:

'use strict';

var express = require('express');
var session = require('express-session');
var app = express();
var shopifyObj = require('shopify-node');
var shopifyConfig = require("./config/config.json");
var _ = require('underscore');
var shopify = require('./lib/modules/shopify');
var product = require('./lib/modules/product');

var fakeDta = {
    user: 'Simba',
};

app.use(session({
  secret: 'dsjkfhklaf',
  resave: false,
  saveUninitialized: true
}));

// Set global middleware function to check for sessions
app.use(function(req, res, next) {
    if (req.session && req.session.user) {
        // check here for the existence of this user and token in the database.
        next();

    } else {
        next();
    }
});

// define middleware function
function checkLogin (req, res, next) {
    if (!req.session.user) {
        req.session.error = 'Access denied!';
        res.redirect('/auth');
    } else {
        next();
    }
};

app.get('/auth', function (req, res) {
    var url = shopify.createURL();
    res.redirect(url);
});

app.get('/handle-o-auth-response', function (req, res) {
    var code = req.query.code;
    _.extend(shopifyConfig, {'code': code});
    shopify.setAccessCode(code, res, function (err, token) {
        if (err) {
            res.redirect('/auth');
        } else {
            _.extend(shopifyConfig, {'access_token': token});
            req.session.user = fakeDta.user;
            res.redirect('/products');
        }
    });
});

app.get('/products', checkLogin, function (req, res) {

    shopify = new shopifyObj(shopifyConfig);

    product.getProducts(shopify, res);

});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('App listening at http://%s:%s', host, port);
});

module.exports = server;

这些是我的测试:

"use strict";

var supertest = require("supertest");

describe("Testing server",function(){
    var server;

    beforeEach(function () {
        /* Node module system caches the evaluated result of each module
        to avoid loading and compiling the same javascript file multiple times.
        Thus the server instance from app.js is only created once.
         */
        delete require.cache[require.resolve('../app.js')];
        server = require('../app.js');
    });

    afterEach(function (done) {
        server.close(done);
    });

    it("should redirect to /auth",function(done){
        supertest(server)
            .get("/products")
            //.expect("Content-type",/json/)
            .expect(302, done);
    });

    it("should redirect to shopify",function(done) {
        supertest(server)
            .get("/auth")
            //.expect("Content-type",/json/)
            .expect(302, done);
    });
});

我要做的是重构代码以支持模拟或替换 checkLogin 函数。

您可以通过在从 app.js 导出的对象上公开 checkLogin 函数来做到这一点,但这在架构上不是很干净。

或者,您可以将 checkLogin 函数分离到它自己的文件中,而不是导出:

module.exports = server;

创建一个采用 checkLogin 函数的函数,该函数包装所有使用 checkLogin 函数的代码:

var express = require('express');
// skipped require code...
var product = require('./lib/modules/product');

function init(checkLogin) {

    var fakeDta = {
        user: 'Simba',
    };

    // skipped code...

    // remove the checkLogin function definition!

    // skipped code...

    return app.listen(3000, function () {
        var host = server.address().address;
        var port = server.address().port;

        console.log('App listening at http://%s:%s', host, port);
    });
};

module.exports = init;

现在,在您的实时代码中,您需要具有 checkLogin 函数的文件,并将该函数传递给服务器,并且在您的测试代码中,您可以提供一个模拟函数,该函数的行为将完全符合您在测试中的要求,例如返回登录有效。

您可以编写自己的函数并传递该函数,或者使用 sinon 等模拟库。

我有 json 个环境配置文件:测试、开发、生产和配置加载器 returns 配置基于当前 NODE_ENV:

let ENV = process.env.NODE_ENV;
let env = ENV || 'prod';

module.exports = require('./' + env + '.json');

在授权中间件中:

if(config.env != 'prod' && process.env.DISABLE_AUTORIZATION) return next();

现在我可以通过像这样设置 DISABLE_AUTHORIZATION 变量来禁用测试和开发环境中中间件的授权:

process.env.DISABLE_AUTORIZATION = true;

PS。要设置 NODE_ENV 我使用包 cross-env。我的脚本:

  "scripts": {
    "start": "node server.js",
    "dev": "cross-env NODE_ENV=dev node server.js",
    "test": "mocha --timeout 10000"
  },