Imagine a toy CDK stack with one S3 bucket:
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
export class BucketStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new s3.Bucket(this, 'MySpecificBucket');
}
}
Importantly, we have specified only the id
of the resource and not its name (i.e., BucketName
). It's good practice not to rely on a specific name since they have to be unique, so even the CDK docs recommend letting CDK autogenerate the name. This is perfectly fine - but how do you now test for the existence of this specific bucket in a Jest test case?
For instance, if we had:
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { BucketStack } from '../lib/bucket-stack';
let template: Template;
beforeAll(async () => {
const app = new cdk.App();
// WHEN
const stack = new BucketStack(app, 'MyTestStack', {});
// THEN
template = Template.fromStack(stack);
});
describe("My test suite", () => {
test("S3 bucket exists", () => {
template.hasResourceProperties("AWS::S3::Bucket", {
BucketName: "wont-work" // this is autogenerated!
});
});
});
The template will have something like:
{
MySpecificBucketF68F3FF0: {
Type: 'AWS::S3::Bucket',
UpdateReplacePolicy: 'Retain',
DeletionPolicy: 'Retain'
}
}
A potential solution could check using a regex for "MySpecificBucket*" to exists, but I guess there are no guarantees what kind of a name CDK will autogenerate. Also, it's not satisfactory to just count the number of S3 buckets via resourceCountIs
because I want to assert the existence of a specific bucket whose name I specifically don't care about. If I just have the id
specified, how can I write a test with these requirements (or should I somehow change my thinking)?
CodePudding user response:
Here are several options to assert the presence of a resource with a specific ID.
Assert with escape hatch syntax:
const bucket = stack.node.tryFindChild("MySpecificBucket");
expect(bucket).toBeDefined();
expect(bucket instanceof s3.Bucket).toBe(true);
expect(bucket?.node.defaultChild instanceof s3.CfnBucket).toBe(true);
Assert with the CDK testing construct and regex:
expect(
Object.keys(template.findResources("AWS::S3::Bucket")).find((key) =>
key.match(/^MySpecificBucket[A-F0-9]{8}$/)
)
).toBeDefined();
If you have many such assertions to make, consider snapshot testing. This is what the CDK itself does. See the @aws-cdk/integ-tests-alpha module.