如何使用Node.js和Passport设置Mocha测试 [英] How to setup Mocha tests with Node.js and Passport

查看:113
本文介绍了如何使用Node.js和Passport设置Mocha测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用Node.js(CompoundJS + PassportJS)构建的应用程序中,如何在锁定并需要登录的控制器上运行Mocha测试?我尝试使用Superagent,但运气不佳,要使用它,服务器需要运行才能运行测试.我已经很接近这种方法了,但是不想让服务器运行来运行单元测试.

In an application built with Node.js (CompoundJS + PassportJS), how can the Mocha tests be run on the controllers that are locked down and require login? I have tried using Superagent but am not having much luck and to use it the server needs to be running to run the tests. I've gotten very close with this method, but don't want to have to have the server running to run unit tests.

我还尝试使用通行证并使用request.login方法,结果到不断出现错误passport.initialize()中间件未使用的地方.

I also tried including passport and using request.login method, I ended up at a point where I kept getting the error passport.initialize() middleware not in use.

我试图坚持使用生成的CompoundJS测试,在涉及身份验证之前,它们一直非常有效.默认的CompoundJS测试运行一个init.js文件,该文件可以很好地处理身份验证并以某种方式可用于每个控制器测试:

I am trying to stick with the generated CompoundJS tests which were working great until the authentication got involved. The default CompoundJS tests run an init.js file which would be nice to handle the authentication in and somehow make available to each controller test:

require('should');
global.getApp = function(done) {
    var app = require('compound').createServer()
    app.renderedViews = [];
    app.flashedMessages = {};

    // Monkeypatch app#render so that it exposes the rendered view files
    app._render = app.render;
    app.render = function(viewName, opts, fn) {
        app.renderedViews.push(viewName);

        // Deep-copy flash messages
        var flashes = opts.request.session.flash;
        for (var type in flashes) {
            app.flashedMessages[type] = [];
            for (var i in flashes[type]) {
                app.flashedMessages[type].push(flashes[type][i]);
            }
        }

        return app._render.apply(this, arguments);
    }

    // Check whether a view has been rendered
    app.didRender = function(viewRegex) {
        var didRender = false;
        app.renderedViews.forEach(function(renderedView) {
            if (renderedView.match(viewRegex)) {
                didRender = true;
            }
        });
        return didRender;
    }

    // Check whether a flash has been called
    app.didFlash = function(type) {
        return !!(app.flashedMessages[type]);
    }

    return app;
};

controllers/users_controller_test.js

var app,
    compound,
    request = require('supertest'),
    sinon = require('sinon');

/** 
 * TODO: User CREATION and EDITs should be tested, with PASSPORT
 * functionality.
 */

function UserStub() {
    return {
        displayName: '',
        email: ''
    };
}

describe('UserController', function() {
    beforeEach(function(done) {
        app = getApp();
        compound = app.compound;
        compound.on('ready', function() {
            done();
        });
    });

    /**
     * GET /users
     * Should render users/index.ejs
     */
    it('should render "index" template on GET /users', function(done) {
        request(app)
            .get('/users')
            .end(function(err, res) {
                res.statusCode.should.equal(200);
                app.didRender(/users\/index\.ejs$/i).should.be.true;
                done();
            });
    });

    /*
     * GET /users/:id
     * Should render users/index.ejs
     */
    it('should access User#find and render "show" template on GET /users/:id',
        function(done) {
            var User = app.models.User;

            // Mock User#find
            User.find = sinon.spy(function(id, callback) {
                callback(null, new User);
            });

            request(app)
                .get('/users/42')
                .end(function(err, res) {
                    res.statusCode.should.equal(200);
                    User.find.calledWith('42').should.be.true;
                    app.didRender(/users\/show\.ejs$/i).should.be.true;

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

这些都以AssertionError: expected 403 to equal 200AssertionError: expected false to be true

推荐答案

我在复合configure事件中使用了模拟模拟passport.initialize,测试助手和侦听器的组合.

I used a combination of mocking passport.initialize, a test helper, and a listener on the compound configure event.

这提供了两件事:

  1. DRY-在控制器测试中重复使用beforeEach代码.
  2. 通俗易懂的测试-模拟护照.初始化,因此我不必根据测试来修改配置.
  1. DRY - reuse of beforeEach code across controller tests.
  2. Unobtrusive testing - mock passport.initialize so I didn't have to modify configuration based on testing.

在test/init.js中,我将该方法添加到模拟passport.initialize **:

In test/init.js I added the method to mock passport.initialize**:

**在以下位置找到它:

** Found it at:

http://hackerpreneurialism.com/post/48344246498/node-js-testing-mocking-authenticated-passport-js

// Fake user login with passport.
app.mockPassportInitialize = function () {
    var passport = require('passport');
    passport.initialize = function () {
        return function (req, res, next) {
            passport = this;
            passport._key = 'passport';
            passport._userProperty = 'user';
            passport.serializeUser = function(user, done) {
                return done(null, user.id);
            };
            passport.deserializeUser = function(user, done) {
                return done(null, user);
            };
            req._passport = {
                instance: passport
            };
            req._passport.session = {
                user: new app.models.User({ id: 1, name: 'Joe Rogan' })
            };

            return next();
        };
    };
};

然后我添加了一个在每个控制器中调用的helpers.js文件:

Then I added a helpers.js file to be called in each controller:

module.exports = {
    prepApp: function (done) {
        var app = getApp();
        compound = app.compound;
        compound.on('configure', function () { app.mockPassportInitialize(); });
        compound.on('ready', function () { done(); });
        return app;
    }
};

这将在每个控制器的beforeEach中调用:

This will be called in the beforeEach of each controller:

describe('UserController', function () {
    beforeEach(function (done) {
        app = require('../helpers.js').prepApp(done);
    });
    [...]
});

这篇关于如何使用Node.js和Passport设置Mocha测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆