как отстаивать обещание поймать с синон и чай - PullRequest
0 голосов
/ 23 мая 2019

В нашем CLI есть метод, который использует метод, возвращающий обещание напечатать сообщение пользователю.

exports.handler = (argv) => {
  let customUtils = new Utils(argv);

  Utils.deploy()
    .then(res => console.log(`Ressource was deployed`))
    .catch(e => {
      console.error(`Ressource was not deployed`);
      console.error(e);
      process.exit(1);
    });
}

Мы ищем способ протестировать ошибки консоли и завершить процесс в случае deploy() отклонения обещания.

Мы попытались использовать заглушку из песочницы, а затем подтвердить в асинхронном тесте:

describe('when promise is errored', () => {
  beforeEach(() => {
    sandbox = sinon.createSandbox();
    utilsStub = sandbox.stub(Utils.prototype, 'deploy').rejects('rejected');
    processStub = sandbox.stub(process, 'exit');
    consoleStub = sandbox.stub(console, 'error');
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('should call deploy and log the error before exiting', async () => {
    await handler({});

    expect(utilsStub).to.have.been.called;
    expect(console.error).to.have.been.called;
  });
});

Этот тест не работает: AssertionError: expected error to have been called at least once, but it was never called.

То же самое происходит, когда мы expect(process.exit).to.have.been.called;. Это никогда не называется.

Мы успешно протестировали деталь then аналогичным образом:

describe('when promise is resolved', () => {
  beforeEach(() => {
    sandbox = sinon.createSandbox();
    utilsStub = sandbox.stub(Utils.prototype, 'deploy').callsFake(() => Promise.resolve('some text'));
    consoleStub = sandbox.stub(console, 'log');
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('should call deploy and print success message', async () => {
    await handler({});

    expect(utilsStub).to.have.been.called;
    expect(console.log).to.have.been.calledWith('Ressource was deployed');
  });
});

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Вы должны уметь await получить результат exports.handler, прежде чем проверять свои утверждения.Вы ожидаете его , но exports.handler не возвращает обещание, поэтому ждать в тесте нечего - exports.handler немедленно возвращает неопределенное значение, поэтому тест выполняет проверки в том же цикле событий до console.error можно вызвать.

Я не уверен, почему вы не видите подобных проблем в тесте, где обещание разрешается.(Возможно, стоит проверить, что этот тест не прошел должным образом)

Это должно помочь:

exports.handler = (argv) => {
  let customUtils = new Utils(argv);

  //Utils.deploy() // <- is that a typo?

    return customUtils.deploy()
      .then(res => console.log(`Ressource was deployed`))
      .catch(e => {
          console.error(`Ressource was not deployed`);
          console.error(e);
          process.exit(1);
       });
}

Также в ваших тестах вы создаете шпиона с:

consoleStub = sandbox.stub(console, 'error');

Нонаписав утверждение прямо на console.error.Я не думаю, что это должно работать:

expect(console.error).to.have.been.called;
// maybe expect(consoleStub)...

С этими изменениями тест проходит для меня и (что более важно) не проходит, когда я не вызываю console.error в catch.

1 голос
/ 23 мая 2019

Есть несколько вещей, чтобы исправить исходный файл и тестовый файл.

Для исходного файла мы должны использовать customUtils для вызова deploy() функции.Так как вы можете использовать async/await, преобразование его из Promise может дать лучший код.

exports.handler = async argv => { // put async
  let customUtils = new Utils(argv);
  try {
    await customUtils.deploy(); // change to await and use customUtils
    console.log(`Ressource was deployed`);
  } catch (e) {
    console.error(`Ressource was not deployed`);
    console.error(e); 
    process.exit(1);
  }
};

Для тестового файла ничего не меняется

describe('when promise is errored', () => {
  beforeEach(() => {
    sandbox = sinon.createSandbox();
    utilsStub = sandbox.stub(Utils.prototype, 'deploy').rejects('rejected');
    processStub = sandbox.stub(process, 'exit');
    consoleStub = sandbox.stub(console, 'error');
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('should call deploy and log the error before exiting', async () => {
    await handler({});

    expect(utilsStub).to.have.been.called;
    expect(console.error).to.have.been.called;
    expect(process.exit).to.have.been.called; // add it
  });
});

ОБНОВЛЕНО:

Если вы все еще хотите использовать обещание, мы должны убедиться, что мы возвращаем обещание.

exports.handler = (argv) => {
  let customUtils = new Utils(argv);

  return customUtils.deploy() // <== specify return here
    .then(res => console.log(`Ressource was deployed`))
    .catch(e => {
      console.error(`Ressource was not deployed`);
      console.error(e);
      process.exit(1);
    });
};

Надеюсь, это поможет

...