无法使用Tape / Sinon对JavaScript函数进行单元测试

时间:2017-06-29 16:18:49

标签: javascript node.js unit-testing sinon node.js-tape

我有一个模块,我想使用Tape和Sinon进行测试。不幸的是我做得不好。这是模块代码:

let config = require('./config');
let request = require('request');
let restify = require('restify');

let certificateUtils = require('utilities');

const validateTheToken = function (token, requestId, callback) {

  const options = {
    url: config.userServiceRootUrl + config.validationPath,
    method: 'POST',
    headers: {
      'token': token,
      'caller': config.callingService,
      'x-request-id': requestId
    }
  };

  if (typeof process.env.CA_STORE !== 'undefined') {
    const certAuth = process.env.CA_STORE + '/trustedCA.pem';
    options.ca = certificateUtils.getAuthorisedCerts(certAuth);
  }

  request(options, function (error, response, body) {
    callback(error, response, body);
  });
};

// add token validation middleware
const authenticateTheToken = function (req, res, next) {
  if (config.enableTokenValidation) {

    const receivedToken = getToken(req);
    if (!receivedToken) {
      return next(new restify.NotAuthorizedError('No token'));
    }

    validateTheToken(receivedToken, req.requestId, function (err, response, body) {
      if (err || response.statusCode != 200) {
        req.logger.error({
          err: err,
          response: response ? {
            statusCode: response.statusCode,
            statusMessage: response.statusMessage,
            body: body
          } : undefined,
        }, 'validation failed');
        return next(new restify.NotAuthorizedError('Not a valid token'));
      } else {
        return next();
      }
    });
  }
  else {
    return next();
  }
};

function getTheToken(req) {


  if (req.headers.token) {
    return req.headers.token;
  } else if (req.headers.user) {
    req.logger.warn({req, user: req.headers.user}, `request was sent with header 'user'`);
    try {
      return JSON.parse(req.headers.user).token;
    } catch (e) {
      req.logger.warn({user: req.headers.user}, `is not valid JSON`);
      return null;
    }
  } else {
    return null;
  }
}

module.exports = {getTheToken, authenticateTheToken};

我怎么能首先测试authenticateTheToken被调用的单元测试?这是我的尝试: test('accessible authenticateTheToken',function(t){

 const tokenAuthentication = require('../tokenAuthentication');
 const authenticateToken = tokenAuth.authenticateToken;

 let req = {
    headers: {
        token: 1
     }
 };
 let res = {};
 let next = {};

 let stub = sinon.stub(tokenAuth, 'getToken');

 stub.yields('next');

 authenticateToken(req, res, next);

 t.equal(authenticateToken.callCount, 1);
 t.end();
 });

当我运行测试时,我发现以下错误:

C:\source\my-project\tokenAuthentication.js:40
    req.logger.error({
              ^

TypeError: Cannot read property 'error' of undefined
    at C:\source\my-project\tokenAuthentication.js:40:19
    at Request._callback (C:\source\my-project\tokenAuthentication.js:25:5)
    at self.callback (C:\source\my-project\node_modules\request\request.js:188:22)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at Request.init (C:\source\my-project\node_modules\request\request.js:234:17)
    at new Request (C:\source\my-project\node_modules\request\request.js:130:8)
    at request (C:\source\my-project\node_modules\request\index.js:54:10)
    at validateTheToken (C:\source\my-project\tokenAuthentication.js:24:3)
    at authenticateTheToken (C:\source\tokenAuthentication.js:38:5)


npm ERR! Test failed.  See above for more details.

1 个答案:

答案 0 :(得分:0)

您在这里嘲笑req,因此您的测试中req需要在您的代码中拥有req的所有属性。这将包括记录器。

req = {
  ...
  logger: {
    warn: () => {},
    error: () => {},
  }
}

req可能有很多属性,因此您可能要么创建一个真正的Request对象,要么使用另一个库来模拟http请求,例如nock