@@ -21,20 +21,20 @@ The `Template` class includes a set of methods for writing assertions against Cl
2121
2222To create ` Template ` from CDK stack, start off with:
2323
24- ``` ts
24+ ``` ts nofixture
2525import { Stack } from ' @aws-cdk/core' ;
2626import { Template } from ' @aws-cdk/assertions' ;
2727
28- const stack = new Stack (... )
29- ...
30- const assert = Template .fromStack (stack );
28+ const stack = new Stack (/* ... */ );
29+ // ...
30+ const template = Template .fromStack (stack );
3131```
3232
3333Alternatively, assertions can be run on an existing CloudFormation template -
3434
35- ``` ts
36- const template = fs . readFileSync ( ' /path/to/ template/file ' );
37- const assert = Template .fromString (template );
35+ ``` ts fixture=init
36+ const templateJson = ' { "Resources": ... } ' ; /* The CloudFormation template as JSON serialized string. */
37+ const template = Template .fromString (templateJson );
3838```
3939
4040## Full Template Match
@@ -43,34 +43,40 @@ The simplest assertion would be to assert that the template matches a given
4343template.
4444
4545``` ts
46- assert . templateMatches ( {
46+ const expected = {
4747 Resources: {
4848 Type: ' Foo::Bar' ,
4949 Properties: {
5050 Baz: ' Qux' ,
5151 },
5252 },
53- });
53+ };
54+
55+ template .templateMatches (expected );
5456```
5557
56- The ` Template ` class also supports [ snapshot
57- testing] ( https://jestjs.io/docs/snapshot-testing ) using jest.
58+ By default, the ` templateMatches() ` API will use the an 'object-like' comparison,
59+ which means that it will allow for the actual template to be a superset of the
60+ given expectation. See [ Special Matchers] ( #special-matchers ) for details on how
61+ to change this.
5862
59- ``` ts
60- // using jest
61- expect (Template .fromStack (stack )).toMatchSnapshot ();
62- ```
63+ Snapshot testing is a common technique to store a snapshot of the output and
64+ compare it during future changes. Since CloudFormation templates are human readable,
65+ they are a good target for åßsnapshot testing.
66+
67+ The ` toJSON() ` method on the ` Template ` can be used to produce a well formatted JSON
68+ of the CloudFormation template that can be used as a snapshot.
6369
64- For non-javascript languages, the ` toJSON() ` can be called to get an in-memory object
65- of the template .
70+ See [ Snapshot Testing in Jest ] ( https://jestjs.io/docs/snapshot-testing ) and [ Snapshot
71+ Testing in Java ] ( https://json-snapshot.github.io/ ) .
6672
6773## Counting Resources
6874
6975This module allows asserting the number of resources of a specific type found
7076in a template.
7177
7278``` ts
73- assert .resourceCountIs (' Foo::Bar' , 2 );
79+ template .resourceCountIs (' Foo::Bar' , 2 );
7480```
7581
7682## Resource Matching & Retrieval
@@ -82,21 +88,23 @@ The following code asserts that the `Properties` section of a resource of type
8288` Foo::Bar ` contains the specified properties -
8389
8490``` ts
85- assert . hasResourceProperties ( ' Foo::Bar ' , {
91+ const expected = {
8692 Foo: ' Bar' ,
8793 Baz: 5 ,
8894 Qux: [ ' Waldo' , ' Fred' ],
89- });
95+ };
96+ template .hasResourceProperties (' Foo::Bar' , expected );
9097```
9198
9299Alternatively, if you would like to assert the entire resource definition, you
93100can use the ` hasResource() ` API.
94101
95102``` ts
96- assert . hasResource ( ' Foo::Bar ' , {
103+ const expected = {
97104 Properties: { Foo: ' Bar' },
98105 DependsOn: [ ' Waldo' , ' Fred' ],
99- });
106+ };
107+ template .hasResource (' Foo::Bar' , expected );
100108```
101109
102110Beyond assertions, the module provides APIs to retrieve matching resources.
@@ -114,28 +122,31 @@ that matches specific properties. The following code asserts that a template con
114122an Output with a ` logicalId ` of ` Foo ` and the specified properties -
115123
116124``` ts
117- assert . hasOutput ( ' Foo ' , {
125+ const expected = {
118126 Value: ' Bar' ,
119127 Export: { Name: ' ExportBaz' },
120- });
128+ };
129+ template .hasOutput (' Foo' , expected );
121130```
122131
123132If you want to match against all Outputs in the template, use ` * ` as the ` logicalId ` .
124133
125134``` ts
126- assert . hasOutput ( ' * ' , {
135+ const expected = {
127136 Value: ' Bar' ,
128137 Export: { Name: ' ExportBaz' },
129- });
138+ };
139+ template .hasOutput (' *' , expected );
130140```
131141
132142` findOutputs() ` will return a set of outputs that match the ` logicalId ` and ` props ` ,
133143and you can use the ` '*' ` special case as well.
134144
135145``` ts
136- const result = assert . findOutputs ( ' * ' , {
146+ const expected = {
137147 Value: ' Fred' ,
138- });
148+ };
149+ const result = template .findOutputs (' *' , expected );
139150expect (result .Foo ).toEqual ({ Value: ' Fred' , Description: ' FooFred' });
140151expect (result .Bar ).toEqual ({ Value: ' Fred' , Description: ' BarFred' });
141152```
@@ -175,18 +186,20 @@ level, the list of keys in the target is a subset of the provided pattern.
175186// }
176187
177188// The following will NOT throw an assertion error
178- assert . hasResourceProperties ( ' Foo::Bar ' , {
189+ const expected = {
179190 Fred: Match .objectLike ({
180191 Wobble: ' Flob' ,
181192 }),
182- });
193+ };
194+ template .hasResourceProperties (' Foo::Bar' , expected );
183195
184196// The following will throw an assertion error
185- assert . hasResourceProperties ( ' Foo::Bar ' , {
197+ const unexpected = {
186198 Fred: Match .objectLike ({
187199 Brew: ' Coffee' ,
188- })
189- });
200+ }),
201+ }
202+ template .hasResourceProperties (' Foo::Bar' , unexpected );
190203```
191204
192205The ` Match.objectEquals() ` API can be used to assert a target as a deep exact
@@ -214,18 +227,20 @@ or outside of any matchers.
214227// }
215228
216229// The following will NOT throw an assertion error
217- assert . hasResourceProperties ( ' Foo::Bar ' , {
230+ const expected = {
218231 Fred: Match .objectLike ({
219232 Bob: Match .absent (),
220233 }),
221- });
234+ };
235+ template .hasResourceProperties (' Foo::Bar' , expected );
222236
223237// The following will throw an assertion error
224- assert . hasResourceProperties ( ' Foo::Bar ' , {
238+ const unexpected = {
225239 Fred: Match .objectLike ({
226240 Wobble: Match .absent (),
227241 }),
228- });
242+ };
243+ template .hasResourceProperties (' Foo::Bar' , unexpected );
229244```
230245
231246The ` Match.anyValue() ` matcher can be used to specify that a specific value should be found
@@ -250,18 +265,20 @@ This matcher can be combined with any of the other matchers.
250265// }
251266
252267// The following will NOT throw an assertion error
253- assert . hasResourceProperties ( ' Foo::Bar ' , {
268+ const expected = {
254269 Fred: {
255270 Wobble: [Match .anyValue (), " Flip" ],
256271 },
257- });
272+ };
273+ template .hasResourceProperties (' Foo::Bar' , expected );
258274
259275// The following will throw an assertion error
260- assert . hasResourceProperties ( ' Foo::Bar ' , {
276+ const unexpected = {
261277 Fred: {
262278 Wimble: Match .anyValue (),
263279 },
264- });
280+ };
281+ template .hasResourceProperties (' Foo::Bar' , unexpected );
265282```
266283
267284### Array Matchers
@@ -284,14 +301,16 @@ This API will perform subset match on the target.
284301// }
285302
286303// The following will NOT throw an assertion error
287- assert . hasResourceProperties ( ' Foo::Bar ' , {
304+ const expected = {
288305 Fred: Match .arrayWith ([' Flob' ]),
289- });
306+ };
307+ template .hasResourceProperties (' Foo::Bar' , expected );
290308
291309// The following will throw an assertion error
292- assert .hasResourceProperties (' Foo::Bar' , Match .objectLike ({
293- Fred: Match .arrayWith ([' Wobble' ]);
294- }});
310+ const unexpected = Match .objectLike ({
311+ Fred: Match .arrayWith ([' Wobble' ]),
312+ });
313+ template .hasResourceProperties (' Foo::Bar' , unexpected );
295314```
296315
297316* Note:* The list of items in the pattern array should be in order as they appear in the
@@ -319,14 +338,16 @@ not match the pattern specified.
319338// }
320339
321340// The following will NOT throw an assertion error
322- assert . hasResourceProperties ( ' Foo::Bar ' , {
341+ const expected = {
323342 Fred: Match .not ([' Flob' ]),
324- });
343+ };
344+ template .hasResourceProperties (' Foo::Bar' , expected );
325345
326346// The following will throw an assertion error
327- assert .hasResourceProperties (' Foo::Bar' , Match .objectLike ({
328- Fred: Match .not ([' Flob' , ' Cat' ]);
329- }});
347+ const unexpected = Match .objectLike ({
348+ Fred: Match .not ([' Flob' , ' Cat' ]),
349+ });
350+ template .hasResourceProperties (' Foo::Bar' , unexpected );
330351```
331352
332353### Serialized JSON
@@ -353,18 +374,20 @@ The `Match.serializedJson()` matcher allows deep matching within a stringified J
353374// }
354375
355376// The following will NOT throw an assertion error
356- assert . hasResourceProperties ( ' Foo::Bar ' , {
377+ const expected = {
357378 Baz: Match .serializedJson ({
358379 Fred: Match .arrayWith ([" Waldo" ]),
359380 }),
360- });
381+ };
382+ template .hasResourceProperties (' Foo::Bar' , expected );
361383
362384// The following will throw an assertion error
363- assert . hasResourceProperties ( ' Foo::Bar ' , {
385+ const unexpected = {
364386 Baz: Match .serializedJson ({
365387 Fred: [" Waldo" , " Johnny" ],
366388 }),
367- });
389+ };
390+ template .hasResourceProperties (' Foo::Bar' , unexpected );
368391```
369392
370393[ Pipeline BuildSpec ] : https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-source.html#cfn-codebuild-project-source-buildspec
@@ -392,37 +415,12 @@ matching resource.
392415
393416const fredCapture = new Capture ();
394417const waldoCapture = new Capture ();
395- assert . hasResourceProperties ( ' Foo::Bar ' , {
418+ const expected = {
396419 Fred: fredCapture ,
397420 Waldo: [" Qix" , waldoCapture ],
398- });
421+ }
422+ template .hasResourceProperties (' Foo::Bar' , expected );
399423
400424fredCapture .asArray (); // returns ["Flob", "Cat"]
401425waldoCapture .asString (); // returns "Qux"
402426```
403-
404- ## Strongly typed languages
405-
406- Some of the APIs documented above, such as ` templateMatches ()` and
407- ` hasResourceProperties ()` accept fluently an arbitrary JSON (like) structure
408- its parameter.
409- This fluency is available only in dynamically typed languages like javascript
410- and Python.
411-
412- For strongly typed languages, like Java, you can achieve similar fluency using
413- any popular JSON deserializer. The following Java example uses ` Gson ` -
414-
415- ` ` ` java
416- // In Java, using text blocks and Gson
417- import com .google .gson .Gson ;
418-
419- String json = " " "
420- {
421- " Foo" : " Bar" ,
422- " Baz" : 5 ,
423- " Qux" : [ " Waldo" , " Fred" ],
424- } " " " ;
425-
426- Map expected = new Gson ().fromJson (json , Map .class );
427- assert .hasResourceProperties (" Foo::Bar" , expected );
428- ` ` `
0 commit comments