Как мне выполнить модульный тест с использованием sinon, mocha - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть следующая реализация.Как мне продолжить модульный тест?Я хочу убедиться, что processData вызывается только один раз при успехе и handleDecryptError вызывается один раз при ошибке.

Мой модульный тест выдает сообщение об ошибке AssertionError: expected 0 to equal 1 для should.equal(getHandleDecryptErrorSpy.callCount, 1);.

Реализация:

let getData = exports.getData = (err, res, param) => {

    ...

    return security.decryptJWE(jweParts[0], jweParts[1], jweParts[2], jweParts[3], jweParts[4], privatekey)
        .then(data => processData(data, param))
        .catch(error => handleDecryptError(error, param));
}

let handleDecryptError = exports.handleDecryptError = (error, param) => {
    log.error(message.ERROR_DECRYPTING.red, error);

    ..

    return;
}

let processData = exports.processData = (momData, param) => {

    log.info(message.SUCCESS.red);

    ...

}

Контрольный пример:

it('6. Response for data is empty string', (done) => {

        let getDecryptJWESpy = sinon.stub(security, "decryptJWE").rejects(message.ERROR_DECRYPTING);
        let getProcessDataSpy = sinon.spy(updateTask, "processData");
        let getHandleDecryptErrorSpy = sinon.spy(updateTask, "handleDecryptError");

        let response = {
            body: "",
            text: ""
        };

        updateTask.getData(null, response, ["TASKID"]);
        should.equal(getDecryptJWESpy.callCount, 1);
        should.equal(getProcessDataSpy.callCount, 0);
        should.equal(getHandleDecryptErrorSpy.callCount, 1);

        done();
    });

Ответы [ 4 ]

0 голосов
/ 02 января 2019

Мое первое предложение - быть последовательным, используя обратный вызов или обещание везде.Поскольку security.decryptJWE использует обещание, мы сделаем getData также использующим обещание.

let getData = exports.getData = (err, res, param) => {
  ...

  // add 'return' so `getData` returns promise
  return security.decryptJWE(jweParts[0], jweParts[1], jweParts[2], jweParts[3], jweParts[4], privatekey)
      .then(data => processData(data, param))
      .catch(error => handleDecryptError(error, param));
}

Похоже, ваш тестовый пример хочет проверить, вызван ли handleDecryptError или нет, поэтому вы должны использовать rejects вместо resolves.Если использовать resolves, он перейдет к processData вместо handleDecryptError.

it('6. Response for data is empty string', () => {

  let getDecryptJWESpy = sinon.stub(security, "decryptJWE").rejects(message.ERROR_DECRYPTING); // update to use rejects
  let getProcessDataSpy = sinon.spy(updateTask, "processData");
  let getHandleDecryptErrorSpy = sinon.spy(updateTask, "handleDecryptError");

  let response = {
      body: "",
      text: ""
  };

  return updateTask.getData(null, response, ["TASKID"]) // add 'return' and 'then'
    .then(() => { // alternatively, we can use `async/await`
      should.equal(getDecryptJWESpy.callCount, 1);
      should.equal(getProcessDataSpy.callCount, 0);
      should.equal(getHandleDecryptErrorSpy.callCount, 1);
    });
});

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

0 голосов
/ 30 декабря 2018

Я думаю, все, что вам нужно сделать, это дождаться обещания.Проще использовать async/await:

it('6. Response for data is empty string', async () => {

    let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
    let getProcessDataSpy = sinon.spy(updateTask, "processData");
    let getHandleDecryptErrorSpy = sinon.spy(updateTask, "handleDecryptError");

    let response = {
        body: "",
        text: ""
    };

    try {
        await updateTask.getData(null, response, ["TASKID"]);
    } catch(ignore) {}

    should.equal(getDecryptJWESpy.callCount, 1);
    should.equal(getProcessDataSpy.callCount, 0);
    should.equal(getHandleDecryptErrorSpy.callCount, 1);
});
0 голосов
/ 02 января 2019

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

В случае успеха проверьте, что processData вызывается только один раз с необходимыми аргументами

КогдаУспешный тест завершается, когда processData вызывается

Следовательно, ваш тестовый пример становится

it('6. Response for data is empty string', (done) => {
  let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
  let getHandleDecryptErrorSpy = sinon.stub(updateTask, "handleDecryptError");
  let getProcessDataSpy = sinon.stub(updateTask, "processData").callsFake(function fakeFn() {
    should.equal(getDecryptJWESpy.callCount, 1);
    should.equal(getProcessDataSpy.callCount, 1);
    should.equal(getHandleDecryptErrorSpy.callCount, 0);
    //The test is done only is this point is reached
    done();
  });

  let response = {
    body: "",
    text: ""
  };
  updateTask.getData(null, response, ["TASKID"]);
});

При сбое, проверьте, что handleDecryptError вызывается только один раз с требуемыми аргументами

При сбоетест завершается, когда handleDecryptError вызывается

Следовательно, ваш тестовый пример становится

it('6. Response for data is empty string', (done) => {
  let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
  let getProcessDataSpy = sinon.stub(updateTask, "processData");
  let getHandleDecryptErrorSpy = sinon.stub(updateTask, "handleDecryptError").callsFake(function fakeFn() {
    should.equal(getDecryptJWESpy.callCount, 1);
    should.equal(getProcessDataSpy.callCount, 0);
    should.equal(getHandleDecryptErrorSpy.callCount, 1);
    //The test is done only is this point is reached
    done();
  });

  let response = {
    body: "",
    text: ""
  };
  updateTask.getData(null, response, ["TASKID"]);
});

Код как таковой может не работать, поскольку я его не проверял, но, по моему мнению, структуратест должен быть как указано выше.

0 голосов
/ 26 декабря 2018

Если вы вернете обещание от updateTask.getData, вы можете вызвать его в тесте и поместить утверждения в then(), прикрепленные к вызову.Теперь тест может дождаться разрешения getData(), прежде чем пытаться выполнить какие-либо утверждения:

it('6. Response for data is empty string', () => { // don't pass done

   return updateTask.getData() // return this promise and mocha will handle it
   .then(() => {
        // assertions will now run at the right time
        should.equal( /* etc */)
   }

Кроме того, если вы не пройдете done, вы можете вернуть обещание из теста, и мокко узнает, когдатест завершен.

Кроме того, поскольку вы используете Sinon - у Sinon есть хорошая библиотека утверждений , которую вы можете использовать как: sinon.assert.calledOnce(getDecryptJWESpy);.Это даст вам более хорошие сообщения о неудаче, что equal.

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