Cloud Development Kit for Terraform - programmatic infrastructure as code using familiar programming languages
Built-in testing utilities for validating CDKTF applications and infrastructure configurations, providing synthesis testing, construct tree validation, and Jest matcher integration.
Core testing utilities for CDKTF applications, providing synthesis and validation capabilities.
/**
* Testing utilities for CDKTF applications
*/
class Testing {
/**
* Create a test app with sensible defaults
* @param options - Optional app configuration
* @returns App instance configured for testing
*/
static app(options?: TestingAppConfig): App;
/**
* Synthesize a stack for testing purposes
* @param stack - Stack to synthesize
* @param runValidations - Whether to run validations
* @returns JSON string of synthesized configuration
*/
static synth(stack: TerraformStack, runValidations?: boolean): string;
/**
* Synthesize a stack to HCL format for testing
* @param stack - Stack to synthesize
* @param runValidations - Whether to run validations
* @param returnMetadata - Whether to include metadata
* @returns HCL string of synthesized configuration
*/
static synthHcl(stack: TerraformStack, runValidations?: boolean, returnMetadata?: boolean): string;
/**
* Synthesize within a callback scope
* @param fn - Callback function that creates constructs
* @returns JSON string of synthesized configuration
*/
static synthScope(fn: IScopeCallback): string;
/**
* Perform full synthesis including all metadata
* @param stack - Stack to synthesize
* @returns Complete synthesized output
*/
static fullSynth(stack: TerraformStack): string;
/**
* Render the construct tree structure
* @param construct - Root construct to render
* @returns String representation of the tree
*/
static renderConstructTree(construct: IConstruct): string;
/**
* Stub the CDKTF version for consistent testing
* @param app - App to stub version for
* @returns Modified app with stubbed version
*/
static stubVersion(app: App): App;
/**
* Enable future flags for testing new features
* @param app - App to enable flags for
* @returns Modified app with future flags
*/
static enableFutureFlags(app: App): App;
/**
* Set up fake cdktf.json path for testing
* @param app - App to configure
* @returns Modified app with fake path
*/
static fakeCdktfJsonPath(app: App): App;
/**
* Setup Jest matchers for CDKTF testing
*/
static setupJest(): void;
// Testing Matcher Methods
static toHaveDataSourceWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
static toHaveDataSource(received: string, resourceType: string): boolean;
static toHaveResourceWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
static toHaveResource(received: string, resourceType: string): boolean;
static toHaveProviderWithProperties(received: string, resourceType: string, properties?: Record<string, any>): boolean;
static toHaveProvider(received: string, resourceType: string): boolean;
static toBeValidTerraform(received: string): boolean;
}Usage Examples:
import { Testing, TerraformStack } from "cdktf";
import { Construct } from "constructs";
import { AwsInstance } from "../.gen/providers/aws/instance";
describe("Infrastructure Tests", () => {
let app: App;
let stack: TerraformStack;
beforeEach(() => {
app = Testing.app();
stack = new TerraformStack(app, "test-stack");
});
test("synthesizes valid terraform", () => {
// Create resources in the stack
new AwsInstance(stack, "instance", {
ami: "ami-12345678",
instanceType: "t2.micro"
});
// Synthesize and validate
const synthesized = Testing.synth(stack);
expect(synthesized).toMatchSnapshot();
});
test("generates correct HCL", () => {
new AwsInstance(stack, "instance", {
ami: "ami-12345678",
instanceType: "t2.micro"
});
const hcl = Testing.synthHcl(stack);
expect(hcl).toContain('resource "aws_instance" "instance"');
});
});CDKTF-specific Jest matchers for testing synthesized infrastructure configurations.
/**
* Jest matcher to check if synthesized config contains a resource
* @param received - Synthesized JSON string
* @param resourceType - Terraform resource type
* @returns Matcher result
*/
function toHaveResource(received: string, resourceType: string): boolean;
/**
* Jest matcher to check if synthesized config contains a resource with specific properties
* @param received - Synthesized JSON string
* @param resourceType - Terraform resource type
* @param properties - Expected properties object
* @returns Matcher result
*/
function toHaveResourceWithProperties(
received: string,
resourceType: string,
properties: Record<string, any>
): boolean;
/**
* Jest matcher to check if synthesized config contains a data source
* @param received - Synthesized JSON string
* @param dataSourceType - Terraform data source type
* @returns Matcher result
*/
function toHaveDataSource(received: string, dataSourceType: string): boolean;
/**
* Jest matcher to check if synthesized config contains a data source with specific properties
* @param received - Synthesized JSON string
* @param dataSourceType - Terraform data source type
* @param properties - Expected properties object
* @returns Matcher result
*/
function toHaveDataSourceWithProperties(
received: string,
dataSourceType: string,
properties: Record<string, any>
): boolean;
/**
* Jest matcher to check if synthesized config contains a provider
* @param received - Synthesized JSON string
* @param providerType - Terraform provider type
* @returns Matcher result
*/
function toHaveProvider(received: string, providerType: string): boolean;
/**
* Jest matcher to check if synthesized config contains a provider with specific properties
* @param received - Synthesized JSON string
* @param providerType - Terraform provider type
* @param properties - Expected properties object
* @returns Matcher result
*/
function toHaveProviderWithProperties(
received: string,
providerType: string,
properties: Record<string, any>
): boolean;
/**
* Jest matcher to validate that the synthesized config is valid Terraform
* @param received - Synthesized JSON string
* @returns Matcher result
*/
function toBeValidTerraform(received: string): boolean;Usage Examples:
import { Testing, TerraformStack } from "cdktf";
import { AwsProvider } from "../.gen/providers/aws/provider";
import { AwsInstance } from "../.gen/providers/aws/instance";
import { DataAwsAmi } from "../.gen/providers/aws/data-aws-ami";
// Setup Jest matchers
Testing.setupJest();
describe("Resource Testing", () => {
test("creates correct resources", () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");
new AwsProvider(stack, "aws", {
region: "us-west-2"
});
new AwsInstance(stack, "web", {
ami: "ami-12345678",
instanceType: "t2.micro",
tags: {
Name: "web-server"
}
});
const synthesized = Testing.synth(stack);
// Test using CDKTF matchers
expect(synthesized).toHaveProvider("aws");
expect(synthesized).toHaveProviderWithProperties("aws", {
region: "us-west-2"
});
expect(synthesized).toHaveResource("aws_instance");
expect(synthesized).toHaveResourceWithProperties("aws_instance", {
instance_type: "t2.micro",
tags: {
Name: "web-server"
}
});
expect(synthesized).toBeValidTerraform();
});
test("includes data sources", () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");
new DataAwsAmi(stack, "ubuntu", {
mostRecent: true,
owners: ["099720109477"]
});
const synthesized = Testing.synth(stack);
expect(synthesized).toHaveDataSource("aws_ami");
});
});Additional utilities for testing complex CDKTF applications.
/**
* Callback function for scope-based synthesis
*/
interface IScopeCallback {
(scope: Construct): void;
}
/**
* Configuration for test apps
*/
interface TestingAppConfig extends AppConfig {
/**
* Whether to enable stack traces in test mode
* @default false
*/
readonly enableStackTrace?: boolean;
/**
* Fake values to use for context
*/
readonly fakeContext?: {[key: string]: any};
}
/**
* Assertion helpers for construct tree testing
*/
class ConstructTreeAssertion {
/**
* Assert that a construct exists in the tree
* @param tree - Construct tree string
* @param path - Path to the construct
*/
static hasConstruct(tree: string, path: string): boolean;
/**
* Assert construct count at a specific level
* @param tree - Construct tree string
* @param level - Tree level to check
* @param count - Expected count
*/
static hasConstructCount(tree: string, level: number, count: number): boolean;
}Usage Examples:
import { Testing, ConstructTreeAssertion } from "cdktf";
test("construct tree structure", () => {
const app = Testing.app();
const stack = new TerraformStack(app, "test");
// Add some constructs
new AwsInstance(stack, "web1", { /* config */ });
new AwsInstance(stack, "web2", { /* config */ });
const tree = Testing.renderConstructTree(app);
expect(ConstructTreeAssertion.hasConstruct(tree, "test/web1")).toBe(true);
expect(ConstructTreeAssertion.hasConstruct(tree, "test/web2")).toBe(true);
expect(ConstructTreeAssertion.hasConstructCount(tree, 2, 2)).toBe(true);
});
test("synthesis with callback", () => {
const synthesized = Testing.synthScope((scope) => {
new TerraformOutput(scope, "test-output", {
value: "test-value"
});
});
expect(synthesized).toContain('"test-output"');
expect(synthesized).toContain('"test-value"');
});