Chai测试中的护照认证

时间:2017-10-27 17:15:35

标签: node.js authentication integration-testing chai passport.js

这是我的第一个使用护照的项目,我是Node的新手。在使用Chai运行集成测试时,我无法将端点识别为已授权。端点是 使用passport和jsonwebtoken库通过令牌身份验证进行保护。以下是导入测试的其他文件;

const chai = require('chai');
const chaiHttp = require('chai-http');
const mongoose = require('mongoose');
const should = chai.should();
const { Session } = require('../models/practiceSession' );
const {User} = require('../models/user');
const { app, runServer, closeServer } = require('../app');
const { TEST_DATABASE_URL } = require('../config/mainConfig');
const {secret} = require('../config/mainConfig');
const jwt = require('jsonwebtoken');
chai.use( chaiHttp );

这是端点的测试;

//test the session endpoints
       it( 'should return a session with proper request', function(){
          const user = new User({
              name: 'random2',
              email: 'random2@random.com',
              password: 'Password2'
            });


          user.save( (err) => {
            if (err){
              console.log( err.message);
              }
          });

          const token = jwt.sign({
            id: user._id,
            userName: user.name,
            level: 0
            }, secret, {
            expiresIn: 60 * 60
            });

          console.log( "user id: ", user._id);
          console.log( 'token is: ', token );

          const practiceRequest = {
            operation: "+",
            number: "10",  ///this will possible need to be sent as a number
            min: "1",
            max: "200"
          };

          return chai.request(app)
            .post('/api/session')
            .set('Authorization', 'Bearer ' + token)
            .send( practiceRequest )
            .then( (res) => {
              res.should.have.status(201);
            })
          });

    });

两个console.log语句确认正在创建用户并且具有_id属性,并且正在使用有效令牌 已创建(已在jwt.io确认。)

这是端点的代码;

router.route("/session")
    .post(passport.authenticate('jwt', { session: false }), jsonParser, ( req, res ) => {
        console.log( req );
        let practiceSession = [];  
        for ( let i = 0; i < req.body.number; i++ ){
            let firstTerm = generateTerm( req.body.min, req.body.max );
            let secondTerm = generateTerm( req.body.min, req.body.max );
            const problem = {  
                operator: req.body.operation,
                firstTerm,
                secondTerm,
                problem: `${ firstTerm } ${ req.body.operation } ${ secondTerm }`,
                correctResponse: generateCorrectResponse( firstTerm, secondTerm, req.body.operation )
            }; 
            practiceSession.push( problem );
        }

    // save session into db sessions collection for use in the training-logic.js
        Session
        .create( {
            userId: req.user._id, 
            problems: practiceSession  
        } )
        .then(
            session => res.status( 201 ).json( session) )
        .catch( err => {
            console.error( err );
            res.status( 500 ).json( { message: 'Internal Server Error' } );
        });
    } );

此端点的测试失败,401响应和简单Error: Unauthorized这不是很多信息 我不知道在哪里继续解决问题。我的理解是,这意味着最初passport.authenticate 在端点处未将令牌识别为有效,即使它已在jwt.io站点上确认为有效。在那儿 生成令牌时我应该包括的其他信息?如果是这样的话?

我看了几个使用护照的例子; one,  two,  three但我做到了  没有看到如何将这些见解应用到我的实现中。

对此的任何帮助将不胜感激。感谢您的时间。

更新:

基于有效令牌上升到端点但仍未被接受的事实,我尝试构建一个带有对用户认证端点的初始调用的promise链,然后使用从那里派生的令牌来测试会话生成端点。这是努力;

     it( 'should return a session with proper request', function(){

       let token; 
       return chai.request(app)
          .post('/api/user/authenticate')
          .send( {
           email: 'random@random.com',
           password: 'password2'
           } )
          .then( (res) => {
            res.should.have.status(200);
            res.should.be.json;
            console.log( res.body );
            token = res.body.token; 
            return token; 
          })
          .catch( (err) => {
            console.log( 'failed at user authentication' );
          })
          .then( ( err, data ) => {
            console.log( 'token value is ', token );
            chai.request( app )
            .post( '/api/session' )
            .set( 'Authorization', `${ token }` )
            .send( {
                operation: "+",
                number: "10",  
                min: "1",
                max: "200"
             })
            .then( res => { 
              console.log( 'second response is ', res );
              res.should.have.status(201);
             } )
            .catch( err => {
              console.log( 'second promise ', err.message );
            })
          })
        });

它仍被Unauthorized拒绝。从测试发送到会话端点的请求中缺少某些内容。与从测试中的promise链发送的对象相比,会话端点中的console.log( req )确认它正在接收添加了大量信息的对象。我不得不在外部作用域中使用token变量来传递chai.request(app)命令之间的值。这与工作应用程序中存在的数据流不同。我不知道如何测试这个;我的理解是,到目前为止我所尝试的并没有给端点足够的数据来验证请求。

非常感谢任何帮助。感谢您的时间。

1 个答案:

答案 0 :(得分:0)

为了跟进,一位朋友帮忙解决了这个问题,并给了我一个解决方案,将其他信息传递回端点 构建令牌。最终的工作模型有一个beforeEach()函数,它将一个虚拟用户添加到测试数据库,然后 将此用户分配给外部作用域中的testUser变量,以便在以后的测试中可以访问它。在实际测试中 端点此testUser变量映射到完整用户架构,用于构建令牌并测试端点。它运行良好,因为端点具有所需的所有属性。这是代码;

describe( 'End-point for practice session resources', function() {

    let testUser;
    let modelSession; 

    before( function() {
      return runServer( TEST_DATABASE_URL );
    });

    beforeEach( function(done){
      addUser()
      .then( user => {
        testUser = user;
        done(); 
      });
    });

和测试;

 it( 'should generate a session with the proper request (POST)', function(){

          const token = jwt.sign({
            id: testUser._id
          }, secret, { expiresIn: 60 * 60 }); 

          return chai.request( app )
              .post( '/api/session' )
              .set( 'Authorization', `Bearer ${ token }` )
              .send( {
                  operation: "+",
                  number: "10",  
                  min: "1",
                  max: "200"
              })
              .then( res => { 
                res.should.have.status(201);
              } )
            })
          });

希望这可以帮助其他人。