如何模拟使用 AWS 资源的打字稿服务和功能?
How to mock typescript services and functions that use AWS resources?
我有一个 Typescript 后端结构,我想为所有功能创建单元测试。我正在使用 JEST 和 aws-skd-mock 来模拟 AWS。我尝试了一些东西,但似乎我做的事情不对。
我有这项服务,我从 ParamterStore 获取参数 (amazon.service.ts):
import * as AWS from "aws-sdk";
export class AmazonService {
parameterStore: AWS.SSM;
constructor() {
this.parameterStore = new AWS.SSM();
}
async getParam(param) {
let self = this;
console.log('IN getPARAM', param);
return new Promise(function(resolve, reject){
self.parameterStore.getParameter({
Name: param,
WithDecryption: true
}, function (err, data) {
if (err) {
console.log('Error ', err);
return resolve({Error: 'ParameterNotFound'})
}
console.log('RES ', data.Parameter.Value);
return resolve(data.Parameter.Value)
})
})
}
}
然后,我模拟整个 amazon.service 文件,我模拟 SSM.getParameter 并在我的测试文件 (amazon.service.spect.ts):
import * as AWSMock from "aws-sdk-mock";
import * as AWS from "aws-sdk";
import {AmazonService} from "./amazon.service";
jest.mock('./amazon.service');
describe('amazon service mock', () => {
let amazonService: AmazonService;
it('should get Parameter from Parameter Store', async () => {
const ssmGetParameterPromise = jest.fn().mockReturnValue({
promise: jest.fn().mockResolvedValue({
Parameter: {
Name: 'NAME',
Type: 'SecureString',
Value: 'VALUE',
Version: 1,
LastModifiedDate: 1546551668.495,
ARN: 'arn:aws:ssm:eu-test-1:123:NAME'
}
})
});
AWSMock.setSDKInstance(AWS);
AWSMock.mock('SSM', 'GetParameter', ssmGetParameterPromise);
amazonService = new AmazonService();
console.log(await amazonService.getParam('NAME'))
await expect(amazonService.getParam('NAME')).resolves.toBe('VALUE')
})
});
当调用 amazonService.getParam 时,我得到 undefined。
正如我在示例中所看到的那样,它们在被模拟后立即初始化 new AWS.SSM() 并从测试中调用它,但我想通过调用我的函数来实现这一点。调用我的函数时似乎没有模拟 SSM。
有什么正确的建议吗?
您不需要模拟 ./amazon.service.ts
模块。这是不使用 aws-sdk-mock
.
的单元测试解决方案
例如
amazon.service.ts
:
import * as AWS from 'aws-sdk';
export class AmazonService {
parameterStore: AWS.SSM;
constructor() {
this.parameterStore = new AWS.SSM();
}
async getParam(param) {
let self = this;
console.log('IN getPARAM', param);
return new Promise(function (resolve, reject) {
self.parameterStore.getParameter(
{
Name: param,
WithDecryption: true,
},
function (err, data) {
if (err) {
console.log('Error ', err);
return resolve({ Error: 'ParameterNotFound' });
}
console.log('RES ', data.Parameter!.Value);
return resolve(data.Parameter!.Value);
},
);
});
}
}
amazon.service.spec.ts
:
import * as AWS from 'aws-sdk';
import { AmazonService } from './amazon.service';
import { mocked } from 'ts-jest/utils';
import { AWSError } from 'aws-sdk';
import { GetParameterResult } from 'aws-sdk/clients/ssm';
jest.mock('aws-sdk', () => {
const mSSMInstance = {
getParameter: jest.fn(),
};
const mSSM = jest.fn(() => mSSMInstance);
return { SSM: mSSM };
});
describe('amazon service mock', () => {
let amazonService: AmazonService;
it('should get Parameter from Parameter Store', async () => {
amazonService = new AmazonService();
expect(AWS.SSM).toBeCalled();
const mSSMInstance = new AWS.SSM();
const mData = {
Parameter: {
Name: 'NAME',
Type: 'SecureString',
Value: 'VALUE',
Version: 1,
LastModifiedDate: new Date(1995, 11, 17),
ARN: 'arn:aws:ssm:eu-test-1:123:NAME',
},
};
mocked(mSSMInstance.getParameter).mockImplementationOnce(
(params, callback?: (err: AWSError | null, data: GetParameterResult) => void): any => {
if (callback) {
callback(null, mData);
}
},
);
const actual = await amazonService.getParam('NAME');
expect(actual).toBe('VALUE');
});
});
带有覆盖率报告的单元测试结果:
PASS Whosebug/61871955/amazon.service.spec.ts (9.613s)
amazon service mock
✓ should get Parameter from Parameter Store (19ms)
console.log
IN getPARAM NAME
at AmazonService.<anonymous> (Whosebug/61871955/amazon.service.ts:12:13)
console.log
RES VALUE
at Whosebug/61871955/amazon.service.ts:24:19
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 86.67 | 50 | 100 | 85.71 |
amazon.service.ts | 86.67 | 50 | 100 | 85.71 | 21-22
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.925s
我有一个 Typescript 后端结构,我想为所有功能创建单元测试。我正在使用 JEST 和 aws-skd-mock 来模拟 AWS。我尝试了一些东西,但似乎我做的事情不对。
我有这项服务,我从 ParamterStore 获取参数 (amazon.service.ts):
import * as AWS from "aws-sdk";
export class AmazonService {
parameterStore: AWS.SSM;
constructor() {
this.parameterStore = new AWS.SSM();
}
async getParam(param) {
let self = this;
console.log('IN getPARAM', param);
return new Promise(function(resolve, reject){
self.parameterStore.getParameter({
Name: param,
WithDecryption: true
}, function (err, data) {
if (err) {
console.log('Error ', err);
return resolve({Error: 'ParameterNotFound'})
}
console.log('RES ', data.Parameter.Value);
return resolve(data.Parameter.Value)
})
})
}
}
然后,我模拟整个 amazon.service 文件,我模拟 SSM.getParameter 并在我的测试文件 (amazon.service.spect.ts):
import * as AWSMock from "aws-sdk-mock";
import * as AWS from "aws-sdk";
import {AmazonService} from "./amazon.service";
jest.mock('./amazon.service');
describe('amazon service mock', () => {
let amazonService: AmazonService;
it('should get Parameter from Parameter Store', async () => {
const ssmGetParameterPromise = jest.fn().mockReturnValue({
promise: jest.fn().mockResolvedValue({
Parameter: {
Name: 'NAME',
Type: 'SecureString',
Value: 'VALUE',
Version: 1,
LastModifiedDate: 1546551668.495,
ARN: 'arn:aws:ssm:eu-test-1:123:NAME'
}
})
});
AWSMock.setSDKInstance(AWS);
AWSMock.mock('SSM', 'GetParameter', ssmGetParameterPromise);
amazonService = new AmazonService();
console.log(await amazonService.getParam('NAME'))
await expect(amazonService.getParam('NAME')).resolves.toBe('VALUE')
})
});
当调用 amazonService.getParam 时,我得到 undefined。
正如我在示例中所看到的那样,它们在被模拟后立即初始化 new AWS.SSM() 并从测试中调用它,但我想通过调用我的函数来实现这一点。调用我的函数时似乎没有模拟 SSM。
有什么正确的建议吗?
您不需要模拟 ./amazon.service.ts
模块。这是不使用 aws-sdk-mock
.
例如
amazon.service.ts
:
import * as AWS from 'aws-sdk';
export class AmazonService {
parameterStore: AWS.SSM;
constructor() {
this.parameterStore = new AWS.SSM();
}
async getParam(param) {
let self = this;
console.log('IN getPARAM', param);
return new Promise(function (resolve, reject) {
self.parameterStore.getParameter(
{
Name: param,
WithDecryption: true,
},
function (err, data) {
if (err) {
console.log('Error ', err);
return resolve({ Error: 'ParameterNotFound' });
}
console.log('RES ', data.Parameter!.Value);
return resolve(data.Parameter!.Value);
},
);
});
}
}
amazon.service.spec.ts
:
import * as AWS from 'aws-sdk';
import { AmazonService } from './amazon.service';
import { mocked } from 'ts-jest/utils';
import { AWSError } from 'aws-sdk';
import { GetParameterResult } from 'aws-sdk/clients/ssm';
jest.mock('aws-sdk', () => {
const mSSMInstance = {
getParameter: jest.fn(),
};
const mSSM = jest.fn(() => mSSMInstance);
return { SSM: mSSM };
});
describe('amazon service mock', () => {
let amazonService: AmazonService;
it('should get Parameter from Parameter Store', async () => {
amazonService = new AmazonService();
expect(AWS.SSM).toBeCalled();
const mSSMInstance = new AWS.SSM();
const mData = {
Parameter: {
Name: 'NAME',
Type: 'SecureString',
Value: 'VALUE',
Version: 1,
LastModifiedDate: new Date(1995, 11, 17),
ARN: 'arn:aws:ssm:eu-test-1:123:NAME',
},
};
mocked(mSSMInstance.getParameter).mockImplementationOnce(
(params, callback?: (err: AWSError | null, data: GetParameterResult) => void): any => {
if (callback) {
callback(null, mData);
}
},
);
const actual = await amazonService.getParam('NAME');
expect(actual).toBe('VALUE');
});
});
带有覆盖率报告的单元测试结果:
PASS Whosebug/61871955/amazon.service.spec.ts (9.613s)
amazon service mock
✓ should get Parameter from Parameter Store (19ms)
console.log
IN getPARAM NAME
at AmazonService.<anonymous> (Whosebug/61871955/amazon.service.ts:12:13)
console.log
RES VALUE
at Whosebug/61871955/amazon.service.ts:24:19
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 86.67 | 50 | 100 | 85.71 |
amazon.service.ts | 86.67 | 50 | 100 | 85.71 | 21-22
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.925s