CDK中SuperNovaStack报错TypeError: Cannot read property 'CONTEXT' of undefined
AWS CDK测试报错:TypeError: Cannot read property 'CONTEXT' of undefined
我是AWS CDK和TypeScript新手,在为CDK包中的新栈SuperNovaStack编写测试代码时遇到报错,报错指向栈构造函数的super调用处。
栈实现代码(super_nova.ts)
import { PublicHostedZone } from 'monocdk/aws-route53'; import { App, Construct, PhysicalName, Stack, StackProps } from 'monocdk'; import { AccountPrincipal, CompositePrincipal, ManagedPolicy, Role, ServicePrincipal } from 'monocdk/aws-iam'; export interface CellProps { cellName: string; region: string; enterpriseIndex: number; stage: string; isPrimary: boolean; disableRollbackAlarm: boolean; componentAccounts: string; } export interface SuperNovaStackProps extends StackProps { readonly cellProps: CellProps; readonly allowedAccountsToDelegate: string[]; } export class SuperNovaStack extends Stack { readonly hostedZone: PublicHostedZone; readonly superNovaRole: Role; constructor(scope: Construct, id: string, props: SuperNovaStackProps) { super(scope, id, { ...props, stackName: `${props.cellProps.cellName}SuperNovaStack`, }); // 创建SuperNova IAM角色 this.superNovaRole = new Role(this, 'SuperNovaRole', { roleName: 'Nova-DO-NOT-DELETE', assumedBy: new ServicePrincipal('nova.aws.internal'), managedPolicies: [ ManagedPolicy.fromAwsManagedPolicyName('AmazonRoute53FullAccess'), ManagedPolicy.fromAwsManagedPolicyName('SecurityAudit'), ], }); // 跨账号委托主体配置 const delegationPrincipal = new CompositePrincipal( ...props.allowedAccountsToDelegate.map((accountId) => new AccountPrincipal(accountId)) ); this.hostedZone = new PublicHostedZone(this, 'HostedZone', { comment: `SuperNova HostedZone. [DO NOT DELETE]`, crossAccountZoneDelegationPrincipal: delegationPrincipal, crossAccountZoneDelegationRoleName: 'fOSGlobalZoneDelegationRole', }); } }
测试代码(test_super_nova.ts)
import { Stack, App } from 'monocdk'; import { SuperNovaStack, CellProps } from '../super_nova'; import { Template } from 'monocdk/assertions'; describe('Super Nova stack creates', () => { let stack: Stack; let superNovaStack: SuperNovaStack; const internalBetaAccount: CellProps = { cellName: 'beta-Enterprise', region: 'us-west-2', enterpriseIndex: 0, stage: 'beta', isPrimary: true, disableRollbackAlarm: false, componentAccounts: '456', }; beforeAll(() => { const app = new App(); superNovaStack = new SuperNovaStack(app, 'SuperNova', { env: { account: '123', region: 'us-west-2' }, cellProps: internalBetaAccount, allowedAccountsToDelegate: ['456'], }); stack = superNovaStack; }); test('contains the cross-account delegation role', () => { const template = Template.fromStack(stack); template.hasResourceProperties('AWS::IAM::Role', { RoleName: 'fOSGlobalZoneDelegationRole', }); }); test('contains the SuperNova role with correct policies', () => { const template = Template.fromStack(stack); template.hasResourceProperties('AWS::IAM::Role', { RoleName: 'Nova-DO-NOT-DELETE', ManagedPolicyArns: [ { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonRoute53FullAccess']] }, { 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/SecurityAudit']] }, ], }); }); });
原报错信息
FAIL dist/lib/__tests__/test_super_nova_stack.js ● Super Nova stack creates › expected role TypeError: Cannot read property 'CONTEXT' of undefined 22 | 23 | constructor(scope: Construct | App, id: string, props: SuperNovaStackProps) { > 24 | super(scope, id, { | ^ 25 | ...props, 26 | stackName: `${props.cellProps.cellName}SuperNovaStack`, at new SuperNovaStack (lib/super_nova.ts:24:9)
问题根源及修复步骤
1. 栈类未继承Stack
原代码中SuperNovaStack没有继承任何CDK构造类(如Stack),但在构造函数中调用了super(),导致CDK内部无法找到构造上下文。修复时需要让SuperNovaStack继承Stack,并导入Stack和StackProps类型。
2. 变量作用域错误
测试代码中beforeAll内部使用const stack和const super_nova,会覆盖外部声明的同名变量,导致测试用例中无法访问正确的栈实例。需要去掉const,直接赋值给外部变量。
3. 未定义类型导致的隐性错误
原代码中SuperNovaStackProps的env和cellProps没有明确类型定义,补充CellProps接口并让SuperNovaStackProps继承StackProps,确保类型安全。
4. 断言方法错误
原测试用例使用expect(super_nova).toContain(...),但super_nova是栈实例而非字符串。正确做法是使用CDK的Template断言工具,检查栈模板中是否存在指定资源。
内容的提问来源于stack exchange,提问作者Meet Nandu
相关产品推荐
相关产品推荐

