请求
AWS CDK v1在2023-06-01上达到了支持结束. 此软件包不再更新,用户应该迁移到 AWS CDK v2.
关于如何移徙的更多信息,请参见: 移动到 AWS CDK v2 指南。 。 。 .
如果你从旧的移民 assert 库中,迁移指南可见于
我们的 GitHub 仓库。 。 。 .
针对 CCDK 应用程序进行写入测试的功能, 重点是 Cloud Formation 模板 .
这个 Template class 包括一套针对 CloudFormation 模板撰写断言的方法. 用其中一个 Template.fromXxx() 创建此类实例的静态方法 .
要创建 Template 从 CDK 堆栈开始,从 :
import { Stack } from '@aws-cdk/core';
import { Template } from '@aws-cdk/assertions';
const stack = new Stack(/* ... */);
// ...
const template = Template.fromStack(stack);
或者,可以在现有的 CloudFormation 模板上运行断言 -
const templateJson = '{ "Resources": ... }'; /* The CloudFormation template as JSON serialized string. */
const template = Template.fromString(templateJson);
完全模板匹配
最简单的断言是,该模板与给定的 模板.
template.templateMatches({
Resources: {
BarLogicalId: {
Type: 'Foo::Bar',
Properties: {
Baz: 'Qux',
},
},
},
});
默认情况下 templateMatches() API 将使用“ 对象类” 比较,
也就是说,它将使实际模板成为超级集
给与期望。 见 特殊火柴 详细介绍如何
来改变这个.
快照测试是存储输出快照和 在未来变化中进行比较。 由于CloudFormation模板是人类可读的, 它们是快速测试的好目标.
这个 toJSON() 方法 Template 可用于生产格式良好的JSON
中,可用作快照的 CloudFormation 模板.
见 Jest 的快照测试 财务报告和审定财务报表 抓图 在 Java 中测试。 。 。 .
资源计算
此模块允许声明所找到特定类型资源的数量 在模板中.
template.resourceCountIs('Foo::Bar', 2);
资源匹配和检索
除了资源计算之外,该模块还允许断言资源与 存在特定属性.
以下代码声称: Properties 资源类型
Foo::Bar 包含指定的属性 -
template.hasResourceProperties('Foo::Bar', {
Foo: 'Bar',
Baz: 5,
Qux: [ 'Waldo', 'Fred' ],
});
或者,如果你想要坚持整个资源定义,你
可以使用 hasResource() API (英语).
template.hasResource('Foo::Bar', {
Properties: { Foo: 'Bar' },
DependsOn: [ 'Waldo', 'Fred' ],
});
除了断言外,模块还提供API来取回匹配资源.
这个 findResources() API 是对 hasResource() API,除了,
它不坚持它的存在,而是返回一组匹配的资源.
默认情况下 hasResource() 财务报告和审定财务报表 hasResourceProperties() API 进行深
部分对象匹配。 此行为可以使用匹配器配置 .
见下文关于 特殊匹配者。 。 。 .
产出和绘图科
模块允许您断言 Cloud Formation 模板包含输出
匹配特定属性。 以下代码声称模板包含
带有一个输出 logicalId 联 合 国 Foo 和指定的属性 -
const expected = {
Value: 'Bar',
Export: { Name: 'ExportBaz' },
};
template.hasOutput('Foo', expected);
如果您想要匹配模板中的所有产出, 请使用 * 作为 logicalId。 。 。 .
template.hasOutput('*', {
Value: 'Bar',
Export: { Name: 'ExportBaz' },
});
findOutputs() 返回一组与 logicalId 财务报告和审定财务报表 props, (中文(简体) ),
并且你可以使用 '*' 特例也一样.
const result = template.findOutputs('*', { Value: 'Fred' });
expect(result.Foo).toEqual({ Value: 'Fred', Description: 'FooFred' });
expect(result.Bar).toEqual({ Value: 'Fred', Description: 'BarFred' });
APIs 互联网档案馆的存檔,存档日期2013-12-02 hasMapping(), (中文(简体) ), findMappings(), (中文(简体) ), hasCondition(),以及 hasCondtions() 提供类似的功能.
特殊火柴
B. 对难民署的期望 hasXxx(), (中文(简体) ), findXxx() 财务报告和审定财务报表 templateMatches()
APIs除了包含文字值,如上例所见,还接受
特别的火柴.
它们作为《公约》的一部分提供 Match 课.
对象匹配器
这个 Match.objectLike() API可以用来断言目标是一个超集
对象.
这个API将在目标上进行深度的部分匹配.
深度部分匹配是对象部分递归匹配的地方. 每一个
级别,目标中的密钥列表是所提供模式的一个子集.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": {
// "Wobble": "Flob",
// "Bob": "Cat"
// }
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.objectLike({
Wobble: 'Flob',
}),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.objectLike({
Brew: 'Coffee',
}),
});
这个 Match.objectEquals() API可以用来断言目标为"深度精确"
相匹配的。 匹配的.
出席和缺席
这个 Match.absent() 匹配器可用于指定特定
数值不应存在于目标上。 可在 Match.objectLike()
或在任何匹配者之外.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": {
// "Wobble": "Flob",
// }
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.objectLike({
Bob: Match.absent(),
}),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.objectLike({
Wobble: Match.absent(),
}),
});
这个 Match.anyValue() 匹配器可用于指定应该找到特定值
在地点。 如果目标位置有无效值, 此匹配器将失败
(即:, null 或者说 undefined) (中文(简体) ).
此相克者可与任何其他相克者相并.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": {
// "Wobble": ["Flob", "Flib"],
// }
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: {
Wobble: [ Match.anyValue(), Match.anyValue() ],
},
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: {
Wimble: Match.anyValue(),
},
});
阵列匹配器
这个 Match.arrayWith() API可用于断言目标等于或是一个子集
的图案阵列.
此 API 将在目标上执行子集匹配 .
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": ["Flob", "Cat"]
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.arrayWith(['Flob']),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', Match.objectLike({
Fred: Match.arrayWith(['Wobble']),
}));
说明: 图案阵列中的项目清单应当按照下列顺序排列: 目标阵列。 失序将被记录为匹配失败 .
或者 Match.arrayEquals() API可用于断言目标为:
完全等于图案数组.
字符串匹配符
这个 Match.stringLikeRegexp() API可用于断言目标与
提供了正则表达式.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Template": "const includeHeaders = true;"
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Template: Match.stringLikeRegexp('includeHeaders = (true|false)'),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Template: Match.stringLikeRegexp('includeHeaders = null'),
});
不匹配者
不匹配者反转搜索模式并匹配路径中的所有模式 不匹配指定的模式.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": ["Flob", "Cat"]
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Fred: Match.not(['Flob']),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', Match.objectLike({
Fred: Match.not(['Flob', 'Cat']),
}));
序列化 JSON
通常,我们发现一些 Cloud Formation 资源类型 声明属性为字符串,
但实际上期望JSON被串成一串.
例如 BuildSpec 财产 AWS::CodeBuild::Project, (中文(简体) ),
页:1 Definition 财产 AWS::StepFunctions::StateMachine, (中文(简体) ),
以命名一对夫妇.
这个 Match.serializedJson() 匹配器允许在字符串 JSON 内进行深度匹配.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Baz": "{ \"Fred\": [\"Waldo\", \"Willow\"] }"
// }
// }
// }
// }
// The following will NOT throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Baz: Match.serializedJson({
Fred: Match.arrayWith(["Waldo"]),
}),
});
// The following will throw an assertion error
template.hasResourceProperties('Foo::Bar', {
Baz: Match.serializedJson({
Fred: ["Waldo", "Johnny"],
}),
});
描述值
上面所记录的匹配者 API 允许在匹配条目中捕获值 (资源,产出,测绘等). 以下代码从 a 抓取字符串 匹配资源.
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": ["Flob", "Cat"],
// "Waldo": ["Qix", "Qux"],
// }
// }
// }
// }
const fredCapture = new Capture();
const waldoCapture = new Capture();
template.hasResourceProperties('Foo::Bar', {
Fred: fredCapture,
Waldo: ["Qix", waldoCapture],
});
fredCapture.asArray(); // returns ["Flob", "Cat"]
waldoCapture.asString(); // returns "Qux"
在捕获后,还可以指定一个嵌入模式,这样只有目标 符合巢穴模式的图案将会被捕获 这种模式可以是字面的或 还有火柴.
// Given a template -
// {
// "Resources": {
// "MyBar1": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": ["Flob", "Cat"],
// }
// }
// "MyBar2": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": ["Qix", "Qux"],
// }
// }
// }
// }
const capture = new Capture(Match.arrayWith(['Cat']));
template.hasResourceProperties('Foo::Bar', {
Fred: capture,
});
capture.asArray(); // returns ['Flob', 'Cat']
当多个资源匹配给定条件时, 每个 Capture 定义
条件将捕获所有匹配值。 它们可以通过使用
页:1 next() API (英语). 以下例子说明:
// Given a template -
// {
// "Resources": {
// "MyBar": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": "Flob",
// }
// },
// "MyBaz": {
// "Type": "Foo::Bar",
// "Properties": {
// "Fred": "Quib",
// }
// }
// }
// }
const fredCapture = new Capture();
template.hasResourceProperties('Foo::Bar', {
Fred: fredCapture,
});
fredCapture.asString(); // returns "Flob"
fredCapture.next(); // returns true
fredCapture.asString(); // returns "Quib"
请求说明
除了模板相配外,我们还提供了用于注释相配的API. 说明 可通过 方面 API (英语). 你可以多了解一些东西 这里。 。 。 .
说你有个 MyAspect (单位:千美元) MyStack 用于 MyAspect数字 :
import * as cdk from '@aws-cdk/core';
import { Construct, IConstruct } from 'constructs';
class MyAspect implements cdk.IAspect {
public visit(node: IConstruct): void {
if (node instanceof cdk.CfnResource && node.cfnResourceType === 'Foo::Bar') {
this.error(node, 'we do not want a Foo::Bar resource');
}
}
protected error(node: IConstruct, message: string): void {
cdk.Annotations.of(node).addError(message);
}
}
class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
const stack = new cdk.Stack();
new cdk.CfnResource(stack, 'Foo', {
type: 'Foo::Bar',
properties: {
Fred: 'Thud',
},
});
cdk.Aspects.of(stack).add(new MyAspect());
}
}
然后我们可以断言堆栈包含预期错误:
// import { Annotations } from '@aws-cdk/assertions';
Annotations.fromStack(stack).hasError(
'/Default/Foo',
'we do not want a Foo::Bar resource',
);
以下是可用的 API Annotations数字 :
hasError(), (中文(简体) ),hasNoError(),以及findError()hasWarning(), (中文(简体) ),hasNoWarning(),以及findWarning()hasInfo(), (中文(简体) ),hasNoInfo(),以及findInfo()
相应 findXxx() API 是对 hasXxx() API, 取而代之的是
它会返回一组匹配的信息.
此外,这套API可以与 Matchers 为了更好的控制.
例如,以下断言也起作用:
Annotations.fromStack(stack).hasError(
'/Default/Foo',
Match.stringLikeRegexp('.*Foo::Bar.*'),
);