0

I have a module that I want to test using Tape and Sinon. Unfortunately I'm not doing very well. Here is the module code:

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};

How could I first of all unit test that authenticateTheToken has been called? Here is my attempt: test('accessed 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();
 });

When I run the test I cam getting the following error:

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.
4

1 回答 1

0

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

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

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

于 2017-06-29T16:26:56.760 回答