【问题标题】:Mocha- Testing Express API With Global MiddlewareMocha- 使用全球中间件测试 Express API
【发布时间】:2015-12-01 10:22:25
【问题描述】:

这是我的第一个快速应用程序,我在为端点编写测试时遇到了一些麻烦。

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

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

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

因为我创建了一个全局中间件函数和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);
    });
});

【问题讨论】:

    标签: node.js express mocha.js supertest


    【解决方案1】:

    我要做的是重构代码以支持模拟或替换 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。

    【讨论】:

      【解决方案2】:

      我有每个用于 env 的 json 配置文件:test、dev、prod 和配置加载器,它们根据当前的 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"
        },
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-06
        • 1970-01-01
        • 2017-11-29
        • 1970-01-01
        • 2016-09-20
        • 2015-03-03
        • 2015-05-11
        相关资源
        最近更新 更多