如何使用Passport验证Supertest请求?

Gal*_*aim 59 mocha.js node.js supertest passport.js

我正在使用Passport.js进行身份验证(本地策略)并使用Mocha和Supertest进行测试.

如何使用Supertest创建会话并进行经过身份验证的请求?

And*_*ndy 53

正如zeMirco指出的那样,底层superagent模块支持会话,为您自动维护cookie.但是,可以通过未记录的功能使用该superagent.agent()功能supertest.

只需使用require('supertest').agent('url')而不是require('supertest')('url'):

var request = require('supertest');
var server = request.agent('http://localhost:3000');

describe('GET /api/getDir', function(){
    it('login', loginUser());
    it('uri that requires user to be logged in', function(done){
    server
        .get('/api/getDir')                       
        .expect(200)
        .end(function(err, res){
            if (err) return done(err);
            console.log(res.body);
            done()
        });
    });
});


function loginUser() {
    return function(done) {
        server
            .post('/login')
            .send({ username: 'admin', password: 'admin' })
            .expect(302)
            .expect('Location', '/')
            .end(onResponse);

        function onResponse(err, res) {
           if (err) return done(err);
           return done();
        }
    };
};
Run Code Online (Sandbox Code Playgroud)

  • 如果你将你的app.js放入```request.agent(app);```它没有正在运行的服务器.酷的东西. (11认同)

zem*_*rco 45

你应该使用superagent.它是较低级别的模块并由其使用supertest.看一下Persisting a agent一节:

var request = require('superagent');
var user1 = request.agent();
user1
  .post('http://localhost:4000/signin')
  .send({ user: 'hunter@hunterloftis.com', password: 'password' })
  .end(function(err, res) {
    // user1 will manage its own cookies
    // res.redirects contains an Array of redirects
  });
Run Code Online (Sandbox Code Playgroud)

现在您可以user1用来进行经过身份验证的请求.

  • 使用这种方法,我需要运行一个测试服务器.是否可以将它与Supertest的服务器一起使用?我正在使用会话cookie(使用Passport)并且它不起作用,我查看来自user1.post的响应,并且cookie不包含用户信息 (4认同)
  • 我让它工作,但只有当我杀死已经运行的开发服务器.超级我不必这样做.任何想法如何让它与superagent很好地发挥?也许听一个不同的端口用于测试环境? (3认同)
  • 你不需要测试服务器.你可以使用你的普通快递app.js. 你看过[例子](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js)了吗?如果你想将测试保存在一个单独的文件中,请将`require(../ app.js)`放入标题中以启动你的应用程序. (2认同)

小智 26

试试这个,

  var request=require('supertest');
  var cookie;
  request(app)
  .post('/login')
  .send({ email: "user@gluck.com", password:'password' })
  .end(function(err,res){
    res.should.have.status(200);
    cookie = res.headers['set-cookie'];
    done();        
  });

  //
  // and use the cookie on the next request
  request(app)
  .get('/v1/your/path')
  .set('cookie', cookie)
  .end(function(err,res){  
    res.should.have.status(200);
    done();        
  });
Run Code Online (Sandbox Code Playgroud)

  • 如果第二个请求放在第一个结束回调中,这可以正常工作. (4认同)

Kev*_* C. 11

作为Andy回答的附录,为了让Supertest为您启动服务器,您可以这样做:

var request = require('supertest');

/**
 * `../server` should point to your main server bootstrap file,
 * which has your express app exported. For example:
 * 
 * var app = express();
 * module.exports = app;
 */
var server = require('../server');

// Using request.agent() is the key
var agent = request.agent(server);

describe('Sessions', function() {

  it('Should create a session', function(done) {
    agent.post('/api/session')
    .send({ username: 'user', password: 'pass' })
    .end(function(err, res) {
      expect(req.status).to.equal(201);
      done();
    });
  });

  it('Should return the current session', function(done) {
    agent.get('/api/session').end(function(err, res) {
      expect(req.status).to.equal(200);
      done();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 应该是`expect(res.status)`而不是`req.status`. (2认同)

Dan*_*.K. 6

对不起,但建议的解决方案都不适用于我.

由于supertest.agent()我无法使用该app实例,我需要事先运行服务器并指定http://127.0.0.1:port,而且我不能使用supertest的期望(断言),我不能使用supertest-as-promisedlib等等...

这个cookies案子根本不适用于我.

所以,我的解决方案是:

如果您使用的是Passport.js,它会使用"Bearer token"机制,您可以在规范中使用以下示例:

var request = require('supertest');
var should = require('should');

var app = require('../server/app.js'); // your server.js file

describe('Some auth-required API', function () {
  var token;

  before(function (done) {
    request(app)
      .post('/auth/local')
      .send({
        email: 'test@example.com',
        password: 'the secret'
      })
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        res.body.should.to.have.property('token');
        token = res.body.token;

        done();
      });
  });

  it('should respond with status code 200 and so on...', function (done) {
    request(app)
      .get('/api/v2/blah-blah')
      .set('authorization', 'Bearer ' + token) // 1) using the authorization header
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        // some `res.body` assertions...

        done();
      });
  });

  it('should respond with status code 200 and so on...', function (done) {
    request(app)
      .get('/api/v2/blah-blah')
      .query({access_token: token}) // 2) using the query string
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function (err, res) {
        if (err) {
          return done(err);
        }

        // some `res.body` assertions...

        done();
      });
  });
});
Run Code Online (Sandbox Code Playgroud)

您可能希望有一个帮助程序函数来验证用户:

test/auth-helper.js

'use strict';

var request = require('supertest');
var app = require('app.js');

/**
 * Authenticate a test user.
 *
 * @param {User} user
 * @param {function(err:Error, token:String)} callback
 */
exports.authenticate = function (user, callback) {
  request(app)
    .post('/auth/local')
    .send({
      email: user.email,
      password: user.password
    })
    .end(function (err, res) {
      if (err) {
        return callback(err);
      }

      callback(null, res.body.token);
    });
};
Run Code Online (Sandbox Code Playgroud)

祝你有一天愉快!