如何模拟单元测试的AWS SQS调用
我在Node应用程序中使用AWS SQS队列,我必须为此编写单元测试用例。为此,我想模拟测试文件中的SQS函数调用sendMessage()
,那么我应该怎么做呢?
我已尝试使用aws-sdk-mock
,但在调用sendMessage()
时,该函数尝试连接到队列URL。
测试文件
import AWSMock from 'aws-sdk-mock'
import sendMessage from '../api/sqs/producer'
describe.only('Test case for SQS SendMessage', () => {
it('should return the UserEvent', async () => {
AWSMock.mock('SQS', 'sendMessage', () => Promise.resolve('Success'))
const res = await sendMessage('testURL', 'data')
console.log('RES', res.response.data)
})
})
生产者档案
const AWS = require('aws-sdk')
const sqs = new AWS.SQS({
region: 'us-east-1'
})
const sendMessage = async (msg, queueUrl) => {
try {
const params = {
MessageBody: JSON.stringify(msg),
QueueUrl: queueUrl
}
const res = await sqs.sendMessage(params).promise()
return res
} catch (err) {
console.log('Error:', `failed to send message ${err}`)
throw new Error(err)
}
}
export { sendMessage as default }
在上面的代码中,我希望Success
作为res
输出
FAIL tests/sendMessage.test.js
● Console
console.log api/sqs/producer/index.js:16
Error: failed to send message UnknownEndpoint: Inaccessible host: `testurl'. This service may not b
e available in the `us-east-1' region.
● Test case for SQS SendMessage › should return the UserEvent
UnknownEndpoint: Inaccessible host: `testurl'. This service may not be available in the `us-east-1' r
egion.
解决方案
以下是解决方案,您不需要aws-sdk-mock
模块,您可以自己模拟aws-sdk
。
index.ts
:
import AWS from 'aws-sdk';
const sqs = new AWS.SQS({
region: 'us-east-1'
});
const sendMessage = async (msg, queueUrl) => {
try {
const params = {
MessageBody: JSON.stringify(msg),
QueueUrl: queueUrl
};
const res = await sqs.sendMessage(params).promise();
return res;
} catch (err) {
console.log('Error:', `failed to send message ${err}`);
throw new Error(err);
}
};
export { sendMessage as default };
index.spec.ts
:
import sendMessage from './';
import AWS from 'aws-sdk';
jest.mock('aws-sdk', () => {
const SQSMocked = {
sendMessage: jest.fn().mockReturnThis(),
promise: jest.fn()
};
return {
SQS: jest.fn(() => SQSMocked)
};
});
const sqs = new AWS.SQS({
region: 'us-east-1'
});
describe.only('Test case for SQS SendMessage', () => {
beforeEach(() => {
(sqs.sendMessage().promise as jest.MockedFunction<any>).mockReset();
});
it('should return the UserEvent', async () => {
expect(jest.isMockFunction(sqs.sendMessage)).toBeTruthy();
expect(jest.isMockFunction(sqs.sendMessage().promise)).toBeTruthy();
(sqs.sendMessage().promise as jest.MockedFunction<any>).mockResolvedValueOnce('mocked data');
const actualValue = await sendMessage('testURL', 'data');
expect(actualValue).toEqual('mocked data');
expect(sqs.sendMessage).toBeCalledWith({ MessageBody: '"testURL"', QueueUrl: 'data' });
expect(sqs.sendMessage().promise).toBeCalledTimes(1);
});
it('should throw an error when send message error', async () => {
const sendMessageErrorMessage = 'network error';
(sqs.sendMessage().promise as jest.MockedFunction<any>).mockRejectedValueOnce(sendMessageErrorMessage);
await expect(sendMessage('testURL', 'data')).rejects.toThrowError(new Error(sendMessageErrorMessage));
expect(sqs.sendMessage).toBeCalledWith({ MessageBody: '"testURL"', QueueUrl: 'data' });
expect(sqs.sendMessage().promise).toBeCalledTimes(1);
});
});
100%覆盖率的单元测试结果:
PASS src/stackoverflow/57585620/index.spec.ts
Test case for SQS SendMessage
✓ should return the UserEvent (7ms)
✓ should throw an error when send message error (6ms)
console.log src/stackoverflow/57585620/index.ts:3137
Error: failed to send message network error
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.453s, estimated 6s
这里是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57585620
相关文章