Проблема с Javascript при использовании let - PullRequest
0 голосов
/ 04 марта 2019

У меня есть следующие js для модульного тестирования обработчика ошибок:

import assert from 'assert';
import deepClone from 'lodash.clonedeep';
import deepEqual from 'lodash.isequal';
import { spy } from 'sinon';
import errorHandler from './index';

function getValidError(constructor = SyntaxError) {
  let error = new constructor();
  error.status = 400;
  error.body = {};
  error.type = 'entity.parse.failed';
  return error;
}

describe('errorHandler', function() {
  let err;
  let req;
  let res;
  let next;
  let clonedRes;
  describe('When the error is not an instance of SyntaxError', function() {
    err = getValidError(Error);
    req = {};
    res = {};
    next = spy();
    clonedRes = deepClone(res);
    errorHandler(err, req, res, next);

    it('should not modify res', function() {
      assert(deepEqual(res, clonedRes));
    });

    it('should call next()', function() {
      assert(next.calledOnce);
    });
  });

  ...(#other test cases all similar to the first)

  describe('When the error is a SyntaxError, with a 400 status, has a `body` property set, and has type `entity.parse.failed`', function() {
    err = getValidError();
    req = {};
    let res = {
      status: spy(),
      set: spy(),
      json: spy()
    };
    let next = spy();
    errorHandler(err, req, res, next);

    it('should set res with a 400 status code', function() {
      assert(res.status.calledOnce);
      assert(res.status.calledWithExactly(400));
    });

    it('should set res with an application/json content-type header', function() {
      assert(res.set.calledOnce);
      assert(res.set.calledWithExactly('Content-Type', 'application/json'));
    });

    it('should set res.json with error code', function() {
      assert(res.json.calledOnce);
      assert(res.json.calledWithExactly({ message: 'Payload should be in JSON format' }));
    });
  });
});

Обратите внимание, что у меня есть let перед res, next и clonedRes в блоке описания для«Когда ошибка - SyntaxError ...».

Если перед ними нет let, в моих тестах возникают сбои.Я не понимаю, почему мне нужно добавить let для них снова, но не для err и req в том же блоке.Может ли кто-нибудь помочь мне с объяснением?

1 Ответ

0 голосов
/ 04 марта 2019

В строгом режиме (и в целом прилично освещенном коде) переменная должна быть объявлена ​​до ее присвоения.Кроме того, переменные const и let должны быть объявлены один раз в блоке и не более.Повторное объявление err (или любой другой переменной), которое уже было объявлено, приведет к ошибке, поэтому вы должны видеть let <varname> только один раз в вашей функции describe('errorHandler':

const describe = cb => cb();

let something;
describe(() => {
  something = 'foo';
});
let something;
describe(() => {
  something = 'bar';
});

Далее describe s внутри describe('errorHandler' уже имеет доступ к области действия err.

Без объявления переменнойВо-первых, присвоение ему в небрежном режиме приведет к тому, что он будет назначен глобальному объекту, что почти всегда нежелательно, и может привести к ошибкам и ошибкам .Например:

// Accidentally implicitly referencing window.status, which can only be a string:

status = false;
if (status) {
  console.log('status is actually truthy!');
}

Тем не менее, часто рекомендуется держать переменные в максимально узкой области - присваивать внешней переменной только тогда, когда нужно значение ввнешняя сфера.Попробуйте объявить переменные только внутри присваивающих их describe, что дает дополнительный бонус: вы можете использовать const вместо let:

describe('When the error is not an instance of SyntaxError', function() {
  const err = getValidError(Error);
  const req = {};
  const res = {};
  const next = spy();
  const clonedRes = deepClone(res);
  errorHandler(err, req, res, next);
  // etc
});
// etc
describe('When the error is a SyntaxError, with a 400 status, has a `body` property set, and has type `entity.parse.failed`', function() {
  const err = getValidError();
  const req = {};
  const res = {
    status: spy(),
    set: spy(),
    json: spy()
  };
  const next = spy();
  // etc
...