如何使用 supertest 和 agent 在 mocha 测试中发出经过身份验证的请求?

Posted

技术标签:

【中文标题】如何使用 supertest 和 agent 在 mocha 测试中发出经过身份验证的请求?【英文标题】:How to make authenticated requests in mocha test using supertest and agent? 【发布时间】:2014-09-07 22:29:05 【问题描述】:

我在登录后无法运行经过身份验证的测试(服务器返回 401 Unauthenticated)。

var should = require('should'),
    _ = require('lodash'),
    app = require('../../../server'),
    mongoose = require('mongoose'),
    User = mongoose.model('User'),
    request = require('supertest');

var user
    , user1;

describe('GET /api/jobs', function () 
    before(function (done) 
        user = new User(
            provider: 'local',
            name: 'Fake User',
            email: 'test@test.com',
            password: 'password'
        );

        // Clear users before testing
        User.remove().exec();

        request(app)
            .post('/api/users')
            .send(user)
            // end handles the response
            .end(function(err, res) 
                if (err) 
                    throw err;
                

                res.should.have.status(200);
                res.body._id.should.exist;

                user1 = request.agent(app); //user1 will be used in all subsequent tests since he's supposed to be authenticated
                user1
                    .post('/api/session')
                    .send( email: user.email, password: user.password )
                    .end(function(err, res) 
                        if ( err ) throw err;
                        // user1 will manage its own cookies
                        // res.redirects contains an Array of redirects
                        res.should.have.status(200);

                        done();
                    );
            );
    );

    afterEach(function (done) 
        User.remove().exec();
        done();
    );

    it('should create a job by user1', function (done) 
        var job = 
            //jobs stuff
        ;

        user1
            .post('/api/jobs')
            .send(job)
            .expect(200) //It fails here, getting 401 Unauthenticated. Session is using passport local strategy
            .expect('Content-Type', /json/)
            .end(function (err, res) 
                if (err) return done(err);
                res.body.should.be.instanceof(Object);

                done();
            );
    );
);

会话正在设置这样的 cookie:

    if (req.user) 
        res.cookie('user', JSON.stringify(req.user.userInfo));
    

【问题讨论】:

【参考方案1】:

犯了一个愚蠢的错误。我使用before() 而不是beforeEach() 来创建和登录用户。

beforeEach(function (done) 
// do stuff before each test
);

afterEach() 正在删除数据库中的 Users

如果有人感兴趣,这里是完整的解决方案:

beforeEach(function (done) 
    // Clear data before testing
    user1 = 
        name: 'Fake User',
        username: 'test',
        email: 'test@test.com',
        password: 'password'
    ;

    user2 = 
        name: 'Fake User2',
        username: 'test2',
        email: 'test2@test.com',
        password: 'password2'
    ;

    job = 
        email: 'job@test.com'
        , title: 'Title'
        , description: 'Job description that is at least 60 characters with much detail'
        , apply: 'Application instructions'
        , company: 'Company'
        , location: 'Location'
    ;

    function createUser1(cb)
        agent1
            .post('/api/users')
            .send(user1)
            .expect(200)
            .end(function(err, res)
                if ( err ) throw err;

                loginUser1.call(null, cb);
            );
    

    function loginUser1(cb)
        agent1
            .post('/api/session')
            .send(
                email: user1.email
                , password: user1.password
            )
            .expect(200)
            .end(function(err, res)
                if ( err ) throw err;

                loggedInUser1 = res.body;

                cb();
            );
    

    function createUser2(cb)
        agent2
            .post('/api/users')
            .expect(200)
            .send(user2)
            .end(function(err, res)
                if (err) throw err;

                loginUser2.call(null, cb);
            );
    

    function loginUser2(cb)
        agent2
            .post('/api/session')
            .send(
                email: user2.email
                , password: user2.password
            )
            .end(function(err, res)
                if ( err ) throw err;

                loggedInUser2 = res.body;

                cb();
            );
    

    async.series([function(cb)
        createUser1(cb);
    , function(cb)
        createUser2(cb);
    ], done);

    //working, but looks like shiet with callbacks
    //      agent1
    //          .post('/api/users')
    //          .send(user1)
    //          .expect(200)
    //          // end handles the response
    //          .end(function(err, res) 
    //              if (err) throw err;
    //
    //              agent1
    //                  .post('/api/session')
    //                  .send(
    //                      email: user1.email
    //                      , password: user1.password
    //                  )
    //                  .expect(200)
    //                  .end(function(err, res) 
    //                      if ( err ) throw err;
    //
    //                      loggedInUser1 = res.body;
    //
    //                      //login the 2nd user
    //                      agent2
    //                          .post('/api/users')
    //                          .expect(200)
    //                          .send(user2)
    //                          // end handles the response
    //                          .end(function(err, res) 
    //                              if (err) throw err;
    //
    //                              agent2
    //                                  .post('/api/session')
    //                                  .send(
    //                                      email: user2.email
    //                                      , password: user2.password
    //                                  )
    //                                  .end(function(err, res) 
    //                                      if ( err ) throw err;
    //
    //                                      loggedInUser2 = res.body;
    //
    //                                      done();
    //                                  );
    //                          );
    //                  );
    //          );
);

afterEach(function (done) 
    User.remove()
        .execQ()
        .then(function()
            return Job.remove().execQ()
        )
        .done(function()
            done();
        );
);

agent1 是作为承诺对象的请求。

var requestp = require("supertest-as-promised");
var agent1 = requestp.agent(app)

【讨论】:

你的“agent1”来自哪里?? var requestp = require("supertest-as-promised")var agent1 = requestp.agent(app) 你能解释一下cb吗,我有点困惑它是什么以及它是什么? cb 只是回调的占位符。它是您传入的函数,它在获取用户后执行。不过,现在使用 async/await 有更好的方法来做到这一点。

以上是关于如何使用 supertest 和 agent 在 mocha 测试中发出经过身份验证的请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Passport 验证 Supertest 请求?

如何使用 superagent/supertest 链接 http 调用?

如何使用 Supertest 对文件上传进行单元测试并发送令牌?

使用 supertest 在快速服务器上开玩笑超时

在 Mocha 测试中使用 Superagent/Supertest 和 Express 应用程序

Supertest 在 Node 中进行 Jest 测试时出现 MaxListenersExceedingWarning 错误