【问题标题】:Access to "req" Object in Supertest After a Response响应后在 Supertest 中访问“req”对象
【发布时间】:2015-01-03 20:22:47
【问题描述】:

有什么方法可以在测试请求的同时/之后直接访问supertest 中的req 对象?我想测试我的passport 策略,所以我想检查req.userreq.session,也许还有其他。我知道我可以测试页面重定向或闪存,因为这些是我的策略所做的,但查看req 对象上是否有用户似乎也很有用。如果这样做,我还可以随时检查有多少用户。

我将使用“本地注册”策略为用户注册,该策略是这样定义的:

'use strict';

// get passport & mongoose
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var UserModel = require('mongoose').model('User');

module.exports = function() {

    // signup function
    passport.use('local-signup', new LocalStrategy({
            passReqToCallback: true // pass the entire request to the callback
        },

        function(req, username, password, done) {

            process.nextTick(function() {

            // find a user with the same username
                UserModel.findOne({username: username}, function(err, user) {

                    // if there is an error, log it then return it
                    if(err) {
                        console.log("Error finding a user in the database: " + err);
                        return done(err);
                    }

                    // if a user was already found
                    if(user) {
                        return done(null, false, "User already exists");
                    }

                    // if we get this far, create a new user from the request body
                    var newUser = new UserModel(req.body);

                    // save it and sign it in
                    newUser.save(function(err) {
                        if(err) {
                            console.log("Error during signup: " + err);
                            return done(err);
                        }
                        return done(null, newUser);
                    });

                });

            });

        }

    ));

};

我使用这种策略的一种方式是这样的:

我的“本地”策略是这样定义的:

'use strict';

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var UserModel = require('mongoose').model('User');

module.exports = function() {

    // create our local passport strategy & use it
    passport.use(new LocalStrategy({

            // use the default names for the username & password fields
            usernameField: 'username',
            passwordField: 'password'
        },

        // main strategy function
        function(username, password, done) {

            // find user with given username
            UserModel.findOne({
                username: username
            },

            // with this username, do this
            function(err, user) {

                // if there's an error, log it then pass it along
                if(err) {
                    console.log("Error during login: " + err);
                    return done(err);
                }

                // if the username and/or password is incorrect, return an error
                // along with a message
                if(!user || !user.authenticate(password)) {
                    return done(null, false, {
                        message: 'Invalid username and/or password'
                    });
                }

                // if everything is correct, return the user document from the database
                return done(null, user);

            });
        }

    ));
};

我使用这两种策略,例如:

app.route(pageName).post(function(req, res, next) {
    passport.authenticate(strategyName, function(err, user, info) {
        if(err || !user) {
            res.status(401).send(info);
        }
        else {
            req.login(user, function(err) {
                if(err) {
                    res.status(400).send(err);
                }
                else {
                    res.send(null);
                }
            });
        }
    })(req, res, next);
});

我试过了

request = require('supertest');
this.authServer = require('../my-server');

request(this.authServer)
    .put('/signup')
    .set('Content-Type', 'application/json')
    .set('Host', 'konneka.org')
    .send(this.fullUser)
    .end(function(req, res, done) {
        console.log(res);
    });

我在 end() 函数中记录的 res 对象(此处显示太长,无法在此处显示)定义了一个 req 对象,但它似乎只有定义的对象和函数请求被打开之前。换句话说,它没有req.userreq.session 或我想要的其他对象,因为它们是在请求完成并启动新请求之后定义的。我注意到它也有状态码,它们仅在请求完成后才定义,所以我一定遗漏了一些东西。

在您测试的请求结束后,有什么方法可以访问 req 对象?还是我完全错误的方式?

【问题讨论】:

  • 你想测试什么样的护照策略?这些 oAuth 策略(如 Facebook 或 Twitter 登录)还是一些自定义策略?您能否发布这些策略的代码和/或配置?
  • 好的。当涉及到req.user 或其他什么时,我没有意识到不同的策略很重要。

标签: node.js express supertest passport.js


【解决方案1】:

你不能使用supertest做你想做的事。

不确定这是否有帮助,但我会添加一些上下文来澄清答案:

supertestsuperagent(客户端)之上的一个包装器,带有一些基本挂钩到express 以启动HTTP 侦听器。实际上,这与启动 express 应用程序、等待它侦听端口、向该端口发出 HTTP 请求并解析结果并没有什么不同。事实上,这正是它的作用。

所以基本上supertest 只能访问您的客户端可以访问的任何内容(浏览器或某些 API 客户端)。换句话说,如果它不在 HTTP 响应正文中,您将无法访问它。 req.userreq.sesssion 是服务器端状态变量,它们(很可能)不在响应中(除非你在做一些奇怪的事情)。

如果你想完全按照你描述的方式进行测试,你将不得不使用一些替代的测试策略,而不是supertest

【讨论】:

  • 您有什么建议吗?我听说过nock,但找不到太多其他的了。
  • 所以我在想supertest 可以在请求之前而不是之后访问请求变量,这是真的,但出于与我想的不同的原因,即supertest位于客户端,而不是服务器。
  • 嘿,希望这个答案有帮助:)!我真的没有灵丹妙药给你。我以前没有听说过 nock,但是快速查看 github 告诉我这可能不是答案。我可以分享我的策略,但我不确定这里是否容易解释。理想情况下,从测试中删除 HTTP 确实是您所需要的。就我而言,我抽象出了 express,以便我可以轻松地测试独立于传输 (HTTP) 的控制器。这确实是关键:在 express 参与之前测试功能。不确定这是否有帮助,但我很乐意在聊天中提供进一步的建议:)
  • 这很有帮助!我不敢相信他们没有 some 库来测试express 的服务器端元素。 this answer,这是一个骗子,说这是因为那是实现,但有理由测试那一面。 req.user,一个。
  • 也许明天我会在聊天中寻求建议。现在我要睡觉了,即使这里还不到 11 点。
【解决方案2】:

当我想这样做时,我发现了这个问题,对我来说,检查请求创建的用户的状态而不是验证 req 对象的内容效果很好。您确实可以访问完整的数据库,我假设您的用户最终会以某种方式结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多