I have a test suite for an EC2 Redis construct that tests if the resource has particular IAM policies attached. I can test if it has all of the values within one test successfully, but when testing if it has each policy individually, only the first test passes. It seems like the order of values in the array of policies can make the test fail, which is not ideal.
I'd like to be able to provide more granular unit tests where a specific test will fail with a description of the policy the test expects, but I'm not able to find anything that might enable this behavior in the AWS CDK assert library. Is there a way to test if an array of properties of a CDK construct includes just one value?
Passes:
test('Redis Instance - should attach all IAM policies in order', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonSSMManagedInstanceCore'
]]
}, {
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonS3ReadOnlyAccess'
]]
}, {
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchAgentServerPolicy'
]]
}]
}))
})
Fails:
test('Redis Instance - should attach AmazonSSMManagedInstanceCore IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonSSMManagedInstanceCore'
]]
}]
}))
})
test('Redis Instance - should attach AmazonS3ReadOnlyAccess IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonS3ReadOnlyAccess'
]]
}]
}))
})
test('Redis Instance - should attach CloudWatchAgentServerPolicy IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchAgentServerPolicy'
]]
}]
}))
})
I have a test suite for an EC2 Redis construct that tests if the resource has particular IAM policies attached. I can test if it has all of the values within one test successfully, but when testing if it has each policy individually, only the first test passes. It seems like the order of values in the array of policies can make the test fail, which is not ideal.
I'd like to be able to provide more granular unit tests where a specific test will fail with a description of the policy the test expects, but I'm not able to find anything that might enable this behavior in the AWS CDK assert library. Is there a way to test if an array of properties of a CDK construct includes just one value?
Passes:
test('Redis Instance - should attach all IAM policies in order', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonSSMManagedInstanceCore'
]]
}, {
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonS3ReadOnlyAccess'
]]
}, {
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchAgentServerPolicy'
]]
}]
}))
})
Fails:
test('Redis Instance - should attach AmazonSSMManagedInstanceCore IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonSSMManagedInstanceCore'
]]
}]
}))
})
test('Redis Instance - should attach AmazonS3ReadOnlyAccess IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/AmazonS3ReadOnlyAccess'
]]
}]
}))
})
test('Redis Instance - should attach CloudWatchAgentServerPolicy IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: [{
'Fn::Join': ['', [
'arn:', { Ref: 'AWS::Partition' }, ':iam::aws:policy/CloudWatchAgentServerPolicy'
]]
}]
}))
})
Share
Improve this question
asked Aug 17, 2021 at 10:50
JT HoukJT Houk
1813 silver badges16 bronze badges
0
2 Answers
Reset to default 11For those using the CDK v2 you can achieve the same with Match.arrayWith and Match.objectLike
template.hasResourceProperties('AWS::IAM::Policy', Match.objectLike({
PolicyDocument: {
Statement: Match.arrayWith([Match.objectLike({
Action: 'secretsmanager:GetSecretValue',
Effect: 'Allow',
Resource: 'arn:aws:secretsmanager:TEST_REGION:TEST_ACCOUNT:secret:YourSecret-??????'
})])
}
}));
https://docs.aws.amazon./cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html
Use arrayWith(objectLike({...}))
to test objects in any position in arrays.
Example
import {
expect as expectCDK,
haveResourceLike,
arrayWith,
objectLike,
// deepObjectLike // sometimes better than objectLike
} from '@aws-cdk/assert';
...
...
test('Redis Instance - should attach CloudWatchAgentServerPolicy IAM policy', () => {
const name = 'test-redis'
const { stack } = createRedisInstance(name)
expect(stack).to(haveResourceLike('AWS::IAM::Role', {
ManagedPolicyArns: arrayWith(
objectLike({ ... }),
)
}))
})
https://www.npmjs./package/@aws-cdk/assert