为什么我在测试中收到 401 响应?

Why am I getting a 401 response in my tests?

我正在尝试在我的 Node / Express / Mongoose 后端中使用身份验证测试路由。

这是测试文件

    var should = require('should');
    var _ = require('lodash');
    var async = require('async');
    var app = require('../../../../app');
    var request = require('supertest');
    var mongoose = require('mongoose');
    var User = mongoose.model('User');
    var Firm = mongoose.model('Firm');
    var firm, user, userPassword, createdFirm, loggedInUser;

    describe('GET /api/firms', function(){

    beforeEach(function (done) {

        firm = new Firm({ 
            company: 'My test company', 
            corporateMail: 'test.com' 
        });

        userPassword = 'password';
        user = new User({
            fistname: 'Fake User',
            lastname: 'Fake User',
            email: 'test@test.com',
            job: 'Partner',
            firmName:firm.company,
            password:userPassword,
            isActivated:true,
            _firmId:firm._id
        });   

        function createFirm(cb){
            request(app)
                .post('/api/firms')
                .send(firm)
                .expect(201)
                .end(function(err, res){
                    if ( err ) throw err;
                    createdFirm = res.body;
                    cb();
                });
        }

        function createUser(cb){
            request(app)
                .post('/api/common/users')
                .send(user)
                .expect(200)
                .end(function(err, res){
                    createdUser = res.body;
                    if ( err ) throw err;
                    cb();
                });
        };

        async.series([function(cb){
            createFirm(cb);
        }, function(cb){
            createUser(cb);
        }], done);    

    });


    afterEach(function (done) {
        firm.remove();
        user.remove();
        done();
    });

    it('should respond with 401 error', function(done) {
        request(app)
          .get('/api/firms')
          .expect(401)
          .end(function(err, res) {
            if (err) return done(err);
            done();
          });
    });

    it('should login', function(done) {
        request(app)
          .post('/auth/local')
          .send({email:user.email, password:user.password})
          .expect(200)
          .end(function(err, res) {
            if (err) return done(err);
            done();
          });
    });

    it('should respond with 200 after login', function(done) {
        request(app)
          .get('/api/firms')
          .expect(200)
          .end(function(err, res) {
            if (err) return done(err);
            done();
          });
    });

});

在工作流程中,首先创建 firm 对象,然后 returns 它的 ID,因此我可以使用 firmId 作为参考来创建用户。

我想在用户通过身份验证后测试 /api/firms 路由,但尽管我进行了各种尝试(使用 superagent,登录 before 部分),但我总是收到 401 响应最后 should 部分而不是预期的 200。

如果您要在浏览器中完成最后 2 次测试,取决于您的设置方式,是的,由于 cookie 和会话,它会起作用,但这里的 /api/firms 测试独立于auth/local 测试。所以 401 是正确的响应。

这实际上取决于您的身份验证设置方式,但您也需要在 /api/firms 测试中进行身份验证。通过再次发送凭据(我的每一个 mocha 测试每次都进行身份验证)或在测试中实施会话,请参阅 this SO post 了解一些方向。

实际上,正如 KJ3 所说,要牢记的重要一点是如何设置身份验证。就我而言,我忘了提及我正在使用 jwt。它的工作方式如下,您提供用户名和密码,服务器 returns 使用 jwt 创建的令牌。

因此在测试中为每个请求发回令牌是有意义的。

实现的方法是首先将认证后的token存储在before部分

    function createUser(cb){
            request(app)
                .post('/api/users')
                .send(user)
                .expect(200)
                .end(function(err, res){
                    if ( err ) throw err;
                    authToken = res.body.token;
                    cb();
                });
        };

然后在请求中添加 .set 并使用正确格式的令牌('Bearer ' + 令牌,在身份验证服务中定义):

    it('should respond with 200', function(done) {
        var authToken = 'Bearer ' + createdUser.token;
        request(app)
          .get('/api/firms')
          .set('Authorization', authToken)
          .expect(200)
          .end(function(err, res) {
            if (err) return done(err);
            done();
          });
    });

如果测试发回 200,这是预期的,如果 .set(...) 被注释掉,则发送 401。

好消息是这是通过 supertest 实现的,所以不需要添加任何东西,不太好的消息是你需要将 .set(...) 添加到每个测试请求。