Home > front end >  Assert for the existence of a specific S3 bucket with a CDK autogenerated name
Assert for the existence of a specific S3 bucket with a CDK autogenerated name

Time:01-23

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.

  • Related