Writing an L3 construct on top of terraconstructs, there is no supported way to assert against a synthesized stack. test/assertions.ts in this repo has exactly the right helper (Template.synth / Template.fromStack), but it lives under test/ and is not part of the published package, so downstream authors have to rediscover it.
Why this is more than a convenience
The helper's own docstring records the reason it exists:
This always runs TerraformStack.prepareStack() as this library heavily depends on it for pre-synth resource generation.
A downstream author who reaches for the obvious Testing.synth(stack) instead gets a silently incomplete template. Concretely, on terraconstructs@0.2.12 + cdktn@0.23.0, this stack:
const role = new aws.iam.Role(stack, "Role", {
assumedBy: new aws.iam.ServicePrincipal("ec2.amazonaws.com"),
managedPolicies: [
aws.iam.ManagedPolicy.fromAwsManagedPolicyName(stack, "Ssm", "AmazonSSMManagedInstanceCore"),
],
});
bucket.grantRead(role);
synthesizes via Testing.synth(stack) to a template containing:
data.aws_iam_policy_document.…DefaultPolicy — with all the expected statements
- no
aws_iam_role_policy
- no
aws_iam_role_policy_attachment
The policy document is there, so assertions written against statements pass, while nothing in the template actually attaches those permissions to the role. I spent a while convinced I had built a role with zero permissions before finding test/assertions.ts. Adding stack.prepareStack() before Testing.synth(stack) produces both resources.
Note on the cdktn side
The Testing.synth half of this is already addressed upstream in open-constructs/cdk-terrain main — Testing.synth(stack, runValidations = true) now runs _runPreparingResolve() (deliberately not full prepareStack(), to avoid injecting a local backend into snapshots). That is unreleased as of cdktn@0.23.0. This issue is only about exporting an assertion helper from terraconstructs so construct authors get the correct behaviour by default rather than needing to know the rule.
Suggestion
Publish the Template helper (e.g. terraconstructs/assertions), or document the prepareStack() requirement prominently for construct authors.
Writing an L3 construct on top of
terraconstructs, there is no supported way to assert against a synthesized stack.test/assertions.tsin this repo has exactly the right helper (Template.synth/Template.fromStack), but it lives undertest/and is not part of the published package, so downstream authors have to rediscover it.Why this is more than a convenience
The helper's own docstring records the reason it exists:
A downstream author who reaches for the obvious
Testing.synth(stack)instead gets a silently incomplete template. Concretely, onterraconstructs@0.2.12+cdktn@0.23.0, this stack:synthesizes via
Testing.synth(stack)to a template containing:data.aws_iam_policy_document.…DefaultPolicy— with all the expected statementsaws_iam_role_policyaws_iam_role_policy_attachmentThe policy document is there, so assertions written against statements pass, while nothing in the template actually attaches those permissions to the role. I spent a while convinced I had built a role with zero permissions before finding
test/assertions.ts. Addingstack.prepareStack()beforeTesting.synth(stack)produces both resources.Note on the cdktn side
The
Testing.synthhalf of this is already addressed upstream inopen-constructs/cdk-terrainmain —Testing.synth(stack, runValidations = true)now runs_runPreparingResolve()(deliberately not fullprepareStack(), to avoid injecting a local backend into snapshots). That is unreleased as ofcdktn@0.23.0. This issue is only about exporting an assertion helper fromterraconstructsso construct authors get the correct behaviour by default rather than needing to know the rule.Suggestion
Publish the
Templatehelper (e.g.terraconstructs/assertions), or document theprepareStack()requirement prominently for construct authors.