Cloud Runner¶
The Durable Execution SDK Test Cloud Runner invokes a deployed Lambda function and polls for completion. Use it to validate IAM permissions, real service integrations, and deployment correctness. The same test assertions you write for local testing work with the cloud runner.
Set up the cloud runner¶
Create a CloudDurableTestRunner with the qualified function name and region. The
runner invokes the function, extracts the execution ARN from the response, and polls
until the execution completes.
import { CloudDurableTestRunner } from "@aws/durable-execution-sdk-js-testing";
import { LambdaClient } from "@aws-sdk/client-lambda";
import { ExecutionStatus } from "@aws-sdk/client-lambda";
const runner = new CloudDurableTestRunner({
functionName: "MyFunction:$LATEST",
client: new LambdaClient({ region: "us-east-1" }),
});
it("runs against a deployed function", async () => {
const result = await runner.run({ payload: { name: "world" } });
expect(result.getStatus()).toBe(ExecutionStatus.SUCCEEDED);
expect(result.getResult()).toBe("hello world");
});
from aws_durable_execution_sdk_python.execution import InvocationStatus
from aws_durable_execution_sdk_python_testing.runner import DurableFunctionCloudTestRunner
def test_runs_against_deployed_function():
runner = DurableFunctionCloudTestRunner(
function_name="MyFunction:$LATEST",
region="us-east-1",
)
result = runner.run(input='{"name": "world"}', timeout=60)
assert result.status is InvocationStatus.SUCCEEDED
assert result.result is not None
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.testing.CloudDurableTestRunner;
class CloudRunnerTest {
@Test
void runsAgainstDeployedFunction() {
var runner = CloudDurableTestRunner.create(
"arn:aws:lambda:us-east-1:123456789012:function:MyFunction:$LATEST",
String.class,
String.class
);
var result = runner.runUntilComplete("{\"name\": \"world\"}");
assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus());
assertNotNull(result.getResult(String.class));
}
}
Deploy before running¶
Cloud mode requires a deployed function. Deploy with your preferred tool before running cloud tests:
After deployment, get the qualified function name or ARN:
aws lambda get-function --function-name MyFunction \
--query 'Configuration.FunctionArn' --output text
Configure polling¶
The runner polls for completion, then retrieves the full operation history for assertions. Configure the poll interval to control how frequently the runner checks for completion.
Pass config: { pollInterval } (in milliseconds) to the constructor:
import { CloudDurableTestRunner } from "@aws/durable-execution-sdk-js-testing";
import { LambdaClient } from "@aws-sdk/client-lambda";
import { ExecutionStatus } from "@aws-sdk/client-lambda";
const runner = new CloudDurableTestRunner({
functionName: "MyFunction:$LATEST",
client: new LambdaClient({ region: "us-east-1" }),
config: { pollInterval: 2000 },
});
it("runs against a deployed function", async () => {
const result = await runner.run({ payload: { name: "world" } });
expect(result.getStatus()).toBe(ExecutionStatus.SUCCEEDED);
});
Pass timeout in seconds to run():
from aws_durable_execution_sdk_python.execution import InvocationStatus
from aws_durable_execution_sdk_python_testing.runner import DurableFunctionCloudTestRunner
def test_runs_with_custom_timeout():
runner = DurableFunctionCloudTestRunner(
function_name="MyFunction:$LATEST",
region="us-east-1",
)
result = runner.run(input='{"name": "world"}', timeout=60)
assert result.status is InvocationStatus.SUCCEEDED
Use withTimeout(Duration) to set the maximum wait time:
import static org.junit.jupiter.api.Assertions.*;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import software.amazon.lambda.durable.model.ExecutionStatus;
import software.amazon.lambda.durable.testing.CloudDurableTestRunner;
class CloudRunnerTimeoutTest {
@Test
void runsWithCustomTimeout() {
var runner = CloudDurableTestRunner
.create(
"arn:aws:lambda:us-east-1:123456789012:function:MyFunction:$LATEST",
String.class,
String.class
)
.withTimeout(Duration.ofSeconds(60));
var result = runner.runUntilComplete("{\"name\": \"world\"}");
assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus());
}
}
Required IAM permissions¶
Cloud mode requires AWS credentials in the environment. The runner uses the default credential chain, so any standard AWS credential configuration works.
The IAM principal running the tests needs these permissions on the target function:
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:GetDurableExecution",
"lambda:GetDurableExecutionHistory"
],
"Resource": "arn:aws:lambda:region:account-id:function:function-name"
}
Troubleshooting¶
Credentials not configured¶
The runner throws when it cannot find AWS credentials. Run aws sts get-caller-identity
to verify your credentials are configured.
Function not found¶
Verify the function name or ARN is correct and the function exists in the target region:
aws lambda get-function --function-name MyFunction.
Execution timeout¶
The function took longer than the configured timeout. Increase the timeout or check the
function logs: aws logs tail /aws/lambda/MyFunction --follow.
Note
SAM CLI also supports invoking deployed functions with sam remote invoke and resolving
callbacks with sam remote callback succeed. See SAM CLI.
See also¶
- Authoring Set up the local test runner.
- Assertions Inspect operation history after a test run.