aws / aws/aws-cdk

nteg-tests-alpha: assert response from invokeFunction call

Open
#34,797 3 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-lambda bug feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

I am trying to write some CDK integration tests, making use of the @aws-cdk/integ-tests-alpha package. In these tests, I have created a custom lambda that allows us to perform HTTP calls to health check endpoints for some resources that are only accessible within the VPC.

However, I am having issues getting the integ-tests-alpha framework to parse the response from the lambda correctly. Note that each of the below examples successfully run the cloudformtion deployment/tests, but the test stack output always shows a failed test, seemingly due to how the result from the lambda is passed back to cloudformation.

I have confirmed that the lambda is deployed and is returning a response along the lines of what I'm expecting, which looks like:
```
{
"statusCode": 200,
"body": {
"message": "Success",
"data": {
...
}
}
}
```

I have tried a number of ways to parse this response using the provided mothods that are available to the invokeFunction() command in the integ-tests-alpha framework, but they all return some sort of error. Below is what I've tried and the return results:

Attempt 1
```
const lambdaInvoke = integ.assertions.invokeFunction(...)
lambdaInvoke.expect(ExpectedResult.objectLike({
Payload: {
statusCode: 200,
body: {
message: "success"
}
}
}))

results from cloudformation output:
{"status":"fail","message":"{\n \"ExecutedVersion\": \"$LATEST\",\n!! Expected type object but received string\n \"Payload\": \"{\\\"statusCode\\\": 200, \\\"body\\\": {\\\"message\\\": \\\"Success\\\", \\\"data\\\": {...}}"
```

Attempt 2:
```
const lambdaInvoke = integ.assertions.invokeFunction(...)
lambdaInvoke.expect(ExpectedResult.stringLikeRegexp('"statusCode":200'))

results from cloudformation output:
{"status":"fail","message":"!! Expected a string, but got 'object'\n!! String '[object Object]' did not match pattern '\"statusCode\":200'\n{\n \"ExecutedVersion\": \"$LATEST\",\n \"Payload\": \"{\\\"statusCode\\\": 200, \\\"body\\\": {\\\"message\\\": \\\"Success\\\", \\\"data\\\": {...}}"
```

I have also tried both:
```
const lambdaInvoke = integ.assertions.invokeFunction(...)
.assertAtPath('message', ExpectedResult.objectLike({
Payload: {
statusCode: 200,
body: {
message: "success"
}
}
}))

returns: "message":"!! Expected type object but received undefined\nundefined"
```
and
```
const lambdaInvoke = integ.assertions.invokeFunction(...)
.assertAtPath('message', ExpectedResult.stringLikeRegexp('"statusCode":200'))

returns "message":"!! Expected a string, but got 'undefined'\n!! String 'undefined' did not match pattern '\"statusCode\":200'\nundefined"
```

I have also tried both of the above `.assertAtPath()` commands with the 'message.Payload' path, but I get the same results.

It appears that there is not a method in the ExpectedResult class that can parse the payload that is returned by the `.invokeFunction()` call.

The documentation does not seem to elaborate in any way on how to parse the returned result from the lambdaInvoke function. There seems to be missing examples on the lambdaInvoke [assertAtPath](https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_integ-tests-alpha.LambdaInvokeFunction.html#assertwbratwbrpathpath-expectedspan-classapi-icon-api-icon-experimental-titlethis-api-element-is-experimental-it-may-change-without-noticespan) documentation which looks like it should be giving an example

### Regression Issue

- [ ] Select this option if this issue appears to be a regression.

### Last Known Working CDK Library Version

_No response_

### Expected Behavior

Methods implemented by the ExpectedResult class should be able to parse the payload returned by the `.invokeFunction()` assertion.

### Current Behavior

Methods implemented by the ExpectedResult class cannot parse the payload returned by the `.invokeFunction()` assertion. The methods appear to require a strict format to be returned by the underlying API call that the `.invokeFunction()` call does not adhere to

### Reproduction Steps

Create a Lambda function that returns an arbitrary response object.

Create a new CDK integration test stack using the @aws-cdk/integ-tests-alpha package

Call the Lambda function using the `invokeFunction()` method:
```
const lambdaInvoke = integ.assertions.invokeFunction({
functionName: <>,
invocationType: InvocationType.REQUEST_RESPONSE
})
```
Expect some result back:
```
lambdaInvoke.expect(ExpectedResult.objectLike({
<>
}))
```

### Possible Solution

_No response_

### Additional Information/Context

_No response_

### AWS CDK Library version (aws-cdk-lib)

aws-cdk-lib@2.200.1

### AWS CDK CLI version

2.1019.1 (build d758c9f)

### Node.js Version

v23.10.0

### OS

Windows 10 22H2

### Language

TypeScript

### Language Version

_No response_

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Reproduce the integration test using @aws-cdk/integ-tests-alpha invokeFunction(), ExpectedResult, and assertAtPath() with the shown Lambda response. Start by comparing the CloudFormation output’s string Payload with the values those matchers receive, then review the LambdaInvokeFunction assertAtPath documentation. Done means the returned payload can be asserted reliably or the documentation clearly explains the required format.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.