Jest - имитация обещанных вызовов SQS - PullRequest
0 голосов
/ 17 июня 2020

Предположим, что у меня есть QueueClass с методом send, который получает некоторые данные в качестве параметра, который затем отправляет в очередь SQS.
Я хочу написать 2 теста:
Один, который проверяет, что ключи MessageBody и QueueUrl имеют переданные ожидаемые значения.
Тот, который в случае ошибки генерирует исключение.

Тестируемый метод выглядит следующим образом:
Мой send метод:

async send(data) {
  return SQS.sendMessage({
    MessageBody: JSON.stringify(data),
    QueueUrl: 'queue_url_here',
  })
    .promise()
    .catch((error) => {
      // Throw exception ...
    });
}

Тест, который у меня есть для этого метода:

const aws = require('aws-sdk');

jest.mock('aws-sdk', () => {
  const SQSMocked = {
    sendMessage: jest.fn().mockReturnThis(),
    promise: jest.fn(),
  };

  return {
    SQS: jest.fn(() => SQSMocked),
  };
});

sqs = new aws.SQS();

test('my test', async () => {
  const data = {};
  await QueueClass.send(data);

  expect(sqs.sendMessage).toHaveBeenCalledWith({
    MessageBody: JSON.stringify(data),
    QueueUrl: 'queue_url_here',
  });
});

Этот тест дает мне следующую ошибку:
TypeError: Cannot read property 'catch' of undefined
Я попытался добавить catch: jest.fn() к объекту SQSMocked точно так же, как и с promise, но продолжала получать ту же ошибку.

Дело в том, что когда я меняю метод, который пытаюсь проверить, он использует try-catch block вместо .promise() и .catch():

async send(data) {
  try {
    return SQS.sendMessage({
      MessageBody: JSON.stringify(data),
      QueueUrl: 'queue_url_here',
    });
  } catch (error) {
    // Throw exception ...
  }
}

мой тест проходит, поэтому я думаю, что это не обязательно проблема правильного издевательства над SQS.

Есть идеи, почему при использовании .promise() и .catch() мой тест не проходит?
Также как я могу проверить se, где в очереди возникает ошибка?
Я бы хотел сделать что-то вроде этого:

  await expect(sqs.sendMessage)
    .resolves
    .toEqual(...);

OR

  await expect(sqs.sendMessage)
    .rejects
    .toThrowError(new Error('Some error thrown.'));

1 Ответ

0 голосов
/ 17 июня 2020

promise заглушен и возвращает undefined, поэтому он не возвращает обещание, которое можно было бы связать. Он должен возвращать обещание, как следует из названия.

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

const mockPromiseFn = jest.fn();
const mockSendMessage = jest.fn().mockReturnThis();

jest.mock('aws-sdk', () => {
  return {
    SQS: jest.fn().mockReturnValue({
      sendMessage: mockSendMessage,
      promise: mockPromiseFn
    })
  };
});

Нет смысла тестировать его с помощью await expect(sqs.sendMessage).rejects..., потому что он проверяет код, который вы только что написали.

Вероятно, это должно быть:

mockPromiseFn.mockRejectedValue(new Error(...));
await expect(QueueClass.send(data)).rejects.toThrowError(...);
expect(mockSendMessage).toBeCalledWith(...);

Это потенциально ошибка:

async send(data) {
  try {
    return SQS.sendMessage(...);
  } catch (error) {
    // Throw exception ...
  }
}

try..catch не может отловить асинхронные ошибки из async return, а также sendMessage возвращаемое значение не было преобразовано в обещание.

Должно быть:

async send(data) {
  try {
    return await SQS.sendMessage(...).promise();
  } catch (error) {
    // Throw exception ...
  }
}
...