开玩笑-模拟承诺的SQS通话

时间:2020-06-17 10:08:51

标签: unit-testing promise mocking jestjs amazon-sqs

让我们假设我有一个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()时我的测试失败?
另外,我该如何测试队列抛出错误的情况?
我希望能够执行以下操作:

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

OR

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

1 个答案:

答案 0 :(得分:0)

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返回中的异步错误,也没有将sendMessage返回值转换为Promise。

应该是:

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