{"id":13602647,"url":"https://github.com/m-radzikowski/aws-sdk-client-mock","last_synced_at":"2025-09-16T08:06:38.358Z","repository":{"id":37585917,"uuid":"338681960","full_name":"m-radzikowski/aws-sdk-client-mock","owner":"m-radzikowski","description":"AWS JavaScript SDK v3 mocks for easy unit testing. 🖋️ Typed 🔬 Tested 📄 Documented 🛠️ Maintained","archived":false,"fork":false,"pushed_at":"2024-10-15T12:49:44.000Z","size":3719,"stargazers_count":884,"open_issues_count":27,"forks_count":44,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-08-09T01:56:26.482Z","etag":null,"topics":["aws","aws-lambda","aws-sdk","mock","testing","unit-testing"],"latest_commit_sha":null,"homepage":"https://m-radzikowski.github.io/aws-sdk-client-mock/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m-radzikowski.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-13T22:23:57.000Z","updated_at":"2025-08-04T23:43:10.000Z","dependencies_parsed_at":"2024-01-16T01:11:18.653Z","dependency_job_id":"314c4dd6-049f-4b1a-8be8-2f5cb1da1c67","html_url":"https://github.com/m-radzikowski/aws-sdk-client-mock","commit_stats":{"total_commits":230,"total_committers":19,"mean_commits":"12.105263157894736","dds":0.4478260869565217,"last_synced_commit":"3981b97a249a05610f8751d86a5c3428959f0112"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/m-radzikowski/aws-sdk-client-mock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-radzikowski%2Faws-sdk-client-mock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-radzikowski%2Faws-sdk-client-mock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-radzikowski%2Faws-sdk-client-mock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-radzikowski%2Faws-sdk-client-mock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m-radzikowski","download_url":"https://codeload.github.com/m-radzikowski/aws-sdk-client-mock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-radzikowski%2Faws-sdk-client-mock/sbom","scorecard":{"id":608072,"data":{"date":"2025-08-11","repo":{"name":"github.com/m-radzikowski/aws-sdk-client-mock","commit":"3981b97a249a05610f8751d86a5c3428959f0112"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/29 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/beta-release.yml:1","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/pr.yml:11","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/beta-release.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/beta-release.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/beta-release.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/beta-release.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/beta-release.yml:81: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/beta-release.yml:90: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/beta-release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/pr.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:88: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:97: update your workflow using https://app.stepsecurity.io/secureworkflow/m-radzikowski/aws-sdk-client-mock/release.yml/main?enable=pin","Info:   0 out of   9 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   8 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"26 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-64vr-g452-qvp3","Warn: Project is vulnerable to: GHSA-9cwx-2883-4wfx","Warn: Project is vulnerable to: GHSA-vg6x-rcgg-rjx6","Warn: Project is vulnerable to: GHSA-x574-m823-4x7w","Warn: Project is vulnerable to: GHSA-4r4m-qw57-chr8","Warn: Project is vulnerable to: GHSA-xcj6-pq6g-qj4x","Warn: Project is vulnerable to: GHSA-356w-63v5-8wf4","Warn: Project is vulnerable to: GHSA-859w-5945-r5v3","Warn: Project is vulnerable to: GHSA-9crc-q9x8-hgqq"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T02:03:31.238Z","repository_id":37585917,"created_at":"2025-08-21T02:03:31.238Z","updated_at":"2025-08-21T02:03:31.238Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275384116,"owners_count":25454910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-lambda","aws-sdk","mock","testing","unit-testing"],"created_at":"2024-08-01T18:01:32.560Z","updated_at":"2025-09-16T08:06:38.336Z","avatar_url":"https://github.com/m-radzikowski.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","aws"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# AWS SDK v3 Client mock\n\nEasy and powerful mocking of AWS SDK v3 Clients.\n\n[![npm aws-sdk-client-mock](https://img.shields.io/npm/v/aws-sdk-client-mock?color=brightgreen\u0026style=flat-square\u0026label=npm+aws-sdk-client-mock)](https://www.npmjs.com/package/aws-sdk-client-mock)\n[![npm aws-sdk-client-mock-jest](https://img.shields.io/npm/v/aws-sdk-client-mock-jest?color=brightgreen\u0026style=flat-square\u0026label=npm+aws-sdk-client-mock-jest)](https://www.npmjs.com/package/aws-sdk-client-mock-jest)\n\n\u003c/div\u003e\n\nLibrary recommended by the AWS SDK for JavaScript team - see the [introductory post on the AWS blog](https://aws.amazon.com/blogs/developer/mocking-modular-aws-sdk-for-javascript-v3-in-unit-tests/).\n\nFeatures:\n\n- 🌊\u0026nbsp; **fluent interface** - declaring behavior is short and readable\n- 🔍\u0026nbsp; **matching options** - defining mock behavior by Command type and/or its input payload\n- 🕵️\u0026nbsp; **spying** - checking if Commands were actually sent\n- 🃏\u0026nbsp; **Jest matchers** - easily verifying sent Commands\n- 🖋️\u0026nbsp; **fully typed** - same type control for declaring mock's behavior as when writing regular code\n- ✅\u0026nbsp; **fully tested** - reliable mocks help instead of impeding\n\nIn action:\n\n![aws-client-mock-example](media/aws-client-mock-example.gif)\n\n### Table of Contents\n\n- [About AWS SDK v3](#about-aws-sdk-v3)\n- [Usage](#usage)\n  - [Install](#install)\n    - [Versions compatibility](#versions-compatibility)\n  - [Import](#import)\n  - [Mock](#mock)\n    - [DynamoDB DocumentClient](#dynamodb-documentclient)\n    - [Lib Storage Upload](#lib-storage-upload)\n    - [S3 GetObjectCommand](#s3-getobjectcommand)\n    - [Paginated operations](#paginated-operations)\n    - [SDK v2-style mocks](#sdk-v2-style-mocks)\n  - [Inspect](#inspect)\n  - [Reset and restore](#reset-and-restore)\n  - [Custom matchers](#custom-matchers)\n    - [Jest](#jest)\n    - [Vitest](#vitest)\n- [API Reference](#api-reference)\n- [AWS Lambda example](#aws-lambda-example)\n- [Caveats](#caveats)\n  - [Mixed @smithy/types versions](#mixed-smithytypes-versions)\n  - [AwsClientStub and strictFunctionTypes](#awsclientstub-and-strictfunctiontypes)\n  - [Order of mock behaviors](#order-of-mock-behaviors)\n  - [Order of type and instance mocks](#order-of-type-and-instance-mocks)\n  - [Using with Mocha](#using-with-mocha)\n\n## About AWS SDK v3\n\nThe [AWS SDK for JavaScript version 3](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html),\nis the new version of SDK to use in Node.js and browser.\nIt comes with modular architecture and improved typing,\nthanks to being written in TypeScript.\n\nThe recommended way of using it is to create a `Client`\nand use it to send `Commands`.\n\nFor example, using SNS Client to publish a message to a topic looks like that:\n\n```typescript\nimport {PublishCommand, SNSClient} from '@aws-sdk/client-sns';\n\nconst sns = new SNSClient({});\nconst result = await sns.send(new PublishCommand({\n  TopicArn: 'arn:aws:sns:us-east-1:111111111111:MyTopic',\n  Message: 'My message',\n}));\n\nconsole.log(`Message published, id: ${result.MessageId}`);\n```\n\nThis library provides an easy way to mock sending `Commands`\nand define returned results depending on the `Command` type and payload.\n\n## Usage\n\n### Install\n\n```bash\nnpm install -D aws-sdk-client-mock\n```\n\n\u003e **Warning**  \n\u003e If you are getting type errors `Argument of type 'typeof SomeClient' is not assignable to parameter of type...`\n\u003e see instructions [here](#mixed-smithytypes-versions).\n\n#### Versions compatibility\n\n| `@aws-sdk/*` | `aws-sdk-client-mock` |\n|--------------|-----------------------|\n| ≥ 3.363.0    | ≥ 3.x                 |\n| \u003c 3.363.0    | 2.x                   |\n\n### Import\n\nCommonJS:\n\n```javascript\nconst {mockClient} = require('aws-sdk-client-mock');\n```\n\nTypeScript / ES6:\n\n```typescript\nimport {mockClient} from 'aws-sdk-client-mock';\n```\n\n### Mock\n\nCreate mock for all instances or for given instance of the AWS SDK Client:\n\n```typescript\nconst snsMock = mockClient(SNSClient);\n\nconst dynamoDB = new DynamoDBClient({});\nconst dynamoDBMock = mockClient(dynamoDB);\n```\n\nBy default, mocked `Client#send()` method returns `undefined`.\n\nUsing the obtained mock instance, you can specify the mock behavior\non receiving various commands to send.\n\nSee the [AwsStub API Reference](https://m-radzikowski.github.io/aws-sdk-client-mock/classes/AwsStub.html)\nfor all available methods or check out the examples below.\n\nSpecify default mock behavior:\n\n```typescript\nsnsMock.onAnyCommand().resolves({});\n\n// same as:\n\nsnsMock.resolves({});\n```\n\nSpecify mock behavior on receiving given command only:\n\n```typescript\nsnsMock\n    .on(PublishCommand)\n    .resolves({\n        MessageId: '12345678-1111-2222-3333-111122223333',\n    });\n```\n\nSpecify mock behavior on receiving given command with given payload only:\n\n```typescript\nsnsMock\n    .on(PublishCommand, {\n        TopicArn: 'arn:aws:sns:us-east-1:111111111111:MyTopic',\n        Message: 'My message',\n    })\n    .resolves({\n        MessageId: '12345678-4444-5555-6666-111122223333',\n    });\n```\n\nNot all payload parameters must be defined to match\n(you can force strict matching by passing third param `strict: true`):\n\n```typescript\nsnsMock\n    .on(PublishCommand, {\n        Message: 'My message',\n    })\n    .resolves({\n        MessageId: '12345678-4444-5555-6666-111122223333',\n    });\n```\n\nSpecify mock behavior on receiving given payload only:\n\n```typescript\nsnsMock\n    .onAnyCommand({\n        TopicArn: 'arn:aws:sns:us-east-1:111111111111:MyTopic',\n        Message: 'My message',\n    })\n    .resolves({\n        MessageId: '12345678-4444-5555-6666-111122223333',\n    });\n```\n\nMultiple behaviors (for different commands and payloads) may be specified\nfor a single mock:\n\n```typescript\nsnsMock\n    .resolves({ // default for any command\n        MessageId: '12345678-1111-2222-3333-111122223333'\n    })\n    .on(PublishCommand)\n    .resolves({ // default for PublishCommand\n        MessageId: '12345678-4444-5555-6666-111122223333'\n    })\n    .on(PublishCommand, {\n        TopicArn: 'arn:aws:sns:us-east-1:111111111111:MyTopic',\n        Message: 'My message',\n    })\n    .resolves({ // for PublishCommand with given input\n        MessageId: '12345678-7777-8888-9999-111122223333',\n    });\n```\n\nSpecify chained behaviors - next behaviors for consecutive calls:\n\n```typescript\nsnsMock\n    .on(PublishCommand)\n    .resolvesOnce({ // for the first command call\n        MessageId: '12345678-1111-1111-1111-111122223333'\n    })\n    .resolvesOnce({ // for the second command call\n        MessageId: '12345678-2222-2222-2222-111122223333'\n    })\n    .resolves({ // for further calls\n        MessageId: '12345678-3333-3333-3333-111122223333'\n    });\n```\n\nSpecify mock throwing an error:\n\n```typescript\nsnsMock\n    .rejects('mocked rejection');\n```\n\n```typescript\nconst throttlingError = new Error('mocked rejection');\nthrottlingError.name = 'ThrottlingException';\n\nsnsMock\n    .rejects(throttlingError);\n```\n\nIn `rejects()`, you can pass a string, an `Error` instance,\nor an object with properties.\nIn each case, it will be converted to an `Error` instance.\n\nSpecify custom mock function:\n\n```typescript\nsnsMock\n    .callsFake(input =\u003e {\n        if (input.Message === 'My message') {\n            return {MessageId: '12345678-1111-2222-3333-111122223333'};\n        } else {\n            throw new Error('mocked rejection');\n        }\n    });\n```\n\nSpecify custom mock function for a specific command (chained behavior):\n\n```typescript\nsnsMock\n    .on(PublishCommand)\n    .callsFake(input =\u003e {\n        if (input.Message === 'My message') {\n            return {MessageId: '12345678-1111-2222-3333-111122223333'};\n        } else {\n            throw new Error('mocked rejection');\n        }\n    });\n```\n\nSpecify result based on Client configuration, i.e. region:\n\n```typescript\nsnsMock\n    .on(PublishCommand)\n    .callsFake(async (input, getClient) =\u003e {\n        const client = getClient();\n        const region = await client.config.region();\n        return {MessageId: region.substring(0, 2)};\n    });\n```\n\nTogether with `resolvesOnce()`, you can also use `rejectsOnce()` and `callsFakeOnce()`\nto specify consecutive behaviors.\n\n#### DynamoDB DocumentClient\n\nYou can mock the `DynamoDBDocumentClient` just like any other Client:\n\n```typescript\nimport {DynamoDBClient} from '@aws-sdk/client-dynamodb';\nimport {DynamoDBDocumentClient, QueryCommand} from '@aws-sdk/lib-dynamodb';\n\nconst ddbMock = mockClient(DynamoDBDocumentClient);\nddbMock.on(QueryCommand).resolves({\n    Items: [{pk: 'a', sk: 'b'}],\n});\n\nconst dynamodb = new DynamoDBClient({});\nconst ddb = DynamoDBDocumentClient.from(dynamodb);\n\nconst query = await ddb.send(new QueryCommand({\n  TableName: 'mock',\n}));\n```\n\n#### Lib Storage Upload\n\nTo mock `@aws-sdk/lib-storage` `Upload` you need to mock all commands\nused [under the hood](https://github.com/aws/aws-sdk-js-v3/blob/main/lib/lib-storage/src/Upload.ts):\n\n```typescript\nimport {S3Client, CreateMultipartUploadCommand, UploadPartCommand} from '@aws-sdk/client-s3';\nimport {Upload} from \"@aws-sdk/lib-storage\";\n\nconst s3Mock = mockClient(S3Client);\n\n// for big files upload:\ns3Mock.on(CreateMultipartUploadCommand).resolves({UploadId: '1'});\ns3Mock.on(UploadPartCommand).resolves({ETag: '1'});\n\n// for small files upload:\ns3ClientMock.on(PutObjectCommand).callsFake(async (input, getClient) =\u003e {\n  getClient().config.endpoint = () =\u003e ({hostname: \"\"}) as any;\n  return {};\n});\n\nconst s3Upload = new Upload({\n    client: new S3Client({}),\n    params: {\n        Bucket: 'mock',\n        Key: 'test',\n        Body: 'x'.repeat(6 * 1024 * 1024), // 6 MB\n    },\n});\n\ns3Upload.on('httpUploadProgress', (progress) =\u003e {\n    console.log(progress);\n});\n\nawait s3Upload.done();\n```\n\nThis way, the  `Upload#done()` will complete successfuly.\n\nTo cause a failure, you need to specify the `rejects()` behavior\nfor one of the AWS SDK Commands used by the `@aws-sdk/lib-storage`.\n\nFor uploading a small file (under the defined multipart upload single part size),\n`lib-storage` sends a `PutObjectCommand`. To make it fail:\n\n```ts\ns3Mock.on(PutObjectCommand).rejects();\n```\n\nFor bigger files, it makes a series of calls including `CreateMultipartUploadCommand`,\n`UploadPartCommand`, and `CompleteMultipartUploadCommand`. Making any of them fail will fail the upload:\n\n```ts\ns3Mock.on(UploadPartCommand).rejects();\n```\n\n#### S3 GetObjectCommand\n\nAWS SDK wraps the stream in the S3 `GetObjectCommand` result to provide utility methods to parse it.\nTo mock it, you need to install the [`@smithy/util-stream`](https://www.npmjs.com/package/@smithy/util-stream) package\nand call the wrapping function `sdkStreamMixin()` on the stream you provide as the command output:\n\n```ts\nimport {GetObjectCommand, S3Client} from '@aws-sdk/client-s3';\nimport {sdkStreamMixin} from '@smithy/util-stream';\nimport {mockClient} from 'aws-sdk-client-mock';\nimport {Readable} from 'stream';\nimport {createReadStream} from 'fs';\n\nconst s3Mock = mockClient(S3Client);\n\nit('mocks get object', async () =\u003e {\n    // create Stream from string\n    const stream = new Readable();\n    stream.push('hello world');\n    stream.push(null); // end of stream\n\n    // alternatively: create Stream from file\n    // const stream = createReadStream('./test/data.txt');\n\n    // wrap the Stream with SDK mixin\n    const sdkStream = sdkStreamMixin(stream);\n\n    s3Mock.on(GetObjectCommand).resolves({Body: sdkStream});\n\n    const s3 = new S3Client({});\n\n    const getObjectResult = await s3.send(new GetObjectCommand({Bucket: '', Key: ''}));\n\n    const str = await getObjectResult.Body?.transformToString();\n\n    expect(str).toBe('hello world');\n});\n```\n\n#### Paginated operations\n\nTo mock a [paginated operation](https://aws.amazon.com/blogs/developer/pagination-using-async-iterators-in-modular-aws-sdk-for-javascript/)\nresults, simply mock the corresponding Command:\n\n```typescript\nimport {DynamoDBClient, paginateQuery, QueryCommand} from '@aws-sdk/client-dynamodb';\nimport {marshall} from '@aws-sdk/util-dynamodb';\n\nconst dynamodbMock = mockClient(DynamoDBClient);\ndynamodbMock.on(QueryCommand).resolves({\n    Items: [\n        marshall({pk: 'a', sk: 'b'}),\n        marshall({pk: 'c', sk: 'd'}),\n    ],\n});\n\nconst dynamodb = new DynamoDBClient({});\nconst paginator = paginateQuery({client: dynamodb}, {TableName: 'mock'});\n\nconst items = [];\nfor await (const page of paginator) {\n    items.push(...page.Items || []);\n}\n```\n\n#### SDK v2-style mocks\n\nThe AWS SDK v3 gives an option to use it similarly to v2 SDK,\nwith command method call instead of `send()`:\n\n```typescript\nimport {SNS} from '@aws-sdk/client-sns';\n\nconst sns = new SNS({});\nconst result = await sns.publish({\n    TopicArn: 'arn:aws:sns:us-east-1:111111111111:MyTopic',\n    Message: 'My message',\n});\n```\n\nAlthough this approach is not recommended by AWS,\nthose calls can be mocked in the standard way:\n\n```typescript\nimport {PublishCommand, SNSClient} from '@aws-sdk/client-sns';\n\nconst snsMock = mockClient(SNSClient);\nsnsMock\n    .on(PublishCommand)\n    .resolves({\n        MessageId: '12345678-1111-2222-3333-111122223333',\n    });\n```\n\nNotice that in mocks you still need to use `SNSClient`, not `SNS`,\nas well as `Command` classes.\n\n### Inspect\n\nInspect received calls:\n\n```typescript\nsnsMock.calls(); // all received calls\nsnsMock.call(0); // first received call\n```\n\nGet calls of a specified command:\n\n```typescript\nsnsMock.commandCalls(PublishCommand)\n```\n\nGet calls of a specified command with given payload\n(you can force strict matching by passing third param `strict: true`):\n\n```typescript\nsnsMock.commandCalls(PublishCommand, {Message: 'My message'})\n```\n\nUnder the hood, the library uses [Sinon.js](https://sinonjs.org/) `stub`.\nYou can get the stub instance to configure and use it directly:\n\n```typescript\nconst snsSendStub = snsMock.send;\n```\n\n### Reset and restore\n\nThe Client mock exposes three [Sinon.js](https://sinonjs.org/) `stub` methods:\n`reset()`, `resetHistory()`, and `restore()`.\n\nThe `reset()` method resets the mock state and behavior.\nThe Client will continue to be mocked, only now with a clean mock instance,\nwithout any behavior (set with methods like `on(...).resolves(...)`) and calls history.\n\n**You should call `clientMock.reset()` before or after every test\n(using `beforeEach()` / `beforeAll()` from your test framework)\nto keep tests independent from each other.**\n\nThe `resetHistory()` only clear mocked client calls history\nthat you access with `mockedClient.call(...)` and `mockedClient.calls()`.\nThe behavior is preserved.\n\nThe `restore()` removes the mock altogether,\nrestoring the normal behavior of `client.send()`.\n\nYou can also pass custom [Sinon Sandbox](https://sinonjs.org/releases/latest/sandbox/)\nwith `mockClient(client, { sandbox: mySandbox })`\nto manage all mocks lifecycle at once.\n\n### Custom matchers\n\n#### Jest\n\nCustom [Jest](https://jestjs.io/) matchers simplify verification\nthat the mocked Client was called with given Commands.\n\nMatchers are published as a separate package. Install it:\n\n```bash\nnpm install -D aws-sdk-client-mock-jest\n```\n\nUsage (notice the `import`):\n\n```ts\nimport 'aws-sdk-client-mock-jest';\n\n// a PublishCommand was sent to SNS\nexpect(snsMock).toHaveReceivedCommand(PublishCommand);\n\n// at least one command was sent to SNS\nexpect(snsMock).toHaveReceivedAnyCommand();\n\n// two PublishCommands were sent to SNS\nexpect(snsMock).toHaveReceivedCommandTimes(PublishCommand, 2);\n\n// a PublishCommand with Message \"hello world\" was sent to SNS\nexpect(snsMock).toHaveReceivedCommandWith(\n    PublishCommand, {Message: 'hello world'}\n);\n\n// a PublishCommand with Message containing \"hello\" was sent to SNS\nexpect(snsMock).toHaveReceivedCommandWith(\n    PublishCommand, {Message: expect.stringContaining('hello')}\n);\n\n// the second command sent to SNS was a PublishCommand with Message \"hello world\"\nexpect(snsMock).toHaveReceivedNthCommandWith(\n    2, PublishCommand, {Message: 'hello world'}\n);\n\n// the second PublishCommand sent to SNS had Message \"hello world\"\nexpect(snsMock).toHaveReceivedNthSpecificCommandWith(\n    2, PublishCommand, {Message: 'hello world'}\n);\n```\n\nShorter aliases exist, like `toReceiveCommandTimes()`.\n\n#### Vitest\n\nUse those matchers with [Vitest](https://vitest.dev/):\n\n```ts\nimport 'aws-sdk-client-mock-jest/vitest';\nimport { expect } from 'vitest';\n\n// a PublishCommand was sent to SNS\nexpect(snsMock).toHaveReceivedCommand(PublishCommand);\n```\n\nTo use the matchers outside of Jest, you can pull in the [expect](https://www.npmjs.com/package/expect) library separately\nand add it to the global scope directly, e.g.:\n\n```ts\nconst {expect} = require(\"expect\");\n(globalThis as any).expect = expect;\nrequire(\"aws-sdk-client-mock-jest\");\n```\n\n## API Reference\n\nSee the [full API Reference](https://m-radzikowski.github.io/aws-sdk-client-mock/).\n\n## AWS Lambda example\n\nExample below uses Jest as a test framework, but mocks will work with any testing library.\n\nLet's take a simple Lambda function that takes a list of messages,\nsends them to SNS topic and returns message IDs:\n\n```typescript\nimport {PublishCommand, SNSClient} from '@aws-sdk/client-sns';\n\nconst snsTopicArn = process.env.SNS_TOPIC_ARN || '';\n\nconst sns = new SNSClient({});\n\nexport const handler = async (event: Event): Promise\u003cstring[]\u003e =\u003e {\n  const promises = event.messages.map(async (msg, idx) =\u003e {\n    const publish = await sns.send(new PublishCommand({\n      TopicArn: snsTopicArn,\n      Message: msg,\n    }));\n    return publish.MessageId!;\n  });\n\n  return await Promise.all(promises);\n};\n\ninterface Event {\n  messages: string[];\n}\n```\n\nThen the tests could look like this:\n\n```typescript\nimport {mockClient} from 'aws-sdk-client-mock';\nimport {PublishCommand, SNSClient} from '@aws-sdk/client-sns';\nimport {handler} from '../src';\n\nconst snsMock = mockClient(SNSClient);\n\n/**\n * To be sure that unit tests are independent from each other,\n * reset mock behavior between the tests.\n */\nbeforeEach(() =\u003e {\n  snsMock.reset();\n});\n\nit('message IDs are returned', async () =\u003e {\n  snsMock.on(PublishCommand).resolves({\n    MessageId: '12345678-1111-2222-3333-111122223333',\n  });\n\n  const result = await handler({\n    messages: ['one', 'two', 'three']\n  });\n\n  expect(result).toHaveLength(3);\n  expect(result[0]).toBe('12345678-1111-2222-3333-111122223333');\n});\n\nit('SNS Client is called with PublishCommand', async () =\u003e {\n  snsMock.on(PublishCommand).resolves({\n    MessageId: '111-222-333',\n  });\n\n  await handler({\n    messages: ['qq', 'xx']\n  });\n\n  expect(snsMock).toHaveReceivedCommandTimes(PublishCommand, 2);\n});\n```\n\nFor more examples, see the [unit tests](packages/aws-sdk-client-mock/test/mockClient.test.ts).\n\n## Caveats\n\n### Mixed @smithy/types versions\n\n\u003e **Note**  \n\u003e Those instructions refer to `@smithy/types` used by AWS SDK v3.363.0 and above.\n\u003e For version below 3.363.0, perform the same steps for the `@aws-sdk/types` package.\n\nIf you have multiple versions of `@smithy/types` installed in your project,\nyou can get type errors similar to this:\n\n```\nTS2345: Argument of type 'typeof DynamoDBDocumentClient' is not assignable to parameter of type 'InstanceOrClassType\u003cClient\u003cServiceInputTypes, MetadataBearer, any\u003e\u003e'.\n  Type 'typeof DynamoDBDocumentClient' is not assignable to type 'ClassType\u003cClient\u003cServiceInputTypes, MetadataBearer, any\u003e\u003e'.\n    The types of 'prototype.middlewareStack.concat' are incompatible between these types.\n      Type '\u003cInputType extends ServiceInputTypes, OutputType extends ServiceOutputTypes\u003e(from: MiddlewareStack\u003cInputType, OutputType\u003e) =\u003e MiddlewareStack\u003c...\u003e' is not assignable to type '\u003cInputType extends ServiceInputTypes, OutputType extends MetadataBearer\u003e(from: MiddlewareStack\u003cInputType, OutputType\u003e) =\u003e MiddlewareStack\u003cInputType, OutputType\u003e'.\n        Types of parameters 'from' and 'from' are incompatible.\n          Property 'identify' is missing in type 'MiddlewareStack\u003cInputType, OutputType\u003e' but required in type 'MiddlewareStack\u003cInputType, ServiceOutputTypes\u003e'.\n```\n\nRun `npm ls @smithy/types` / `pnpm why @smithy/types` / `yarn why @smithy/types`\nand check if you have more than one version of the package installed.\n\nTo solve this, go through the steps until one works:\n\n- make sure all your `@aws-sdk/*` packages point to the same version,\n- remove all `@aws-sdk/*` packages from `package.json`, run `npm install` / `pnpm install` / `yarn install`,\n  restore `@aws-sdk/*` packages in `package.json`, and run install again,\n- add `@smithy/types` to your dev dependencies in the latest version,\n- force using single `@smithy/types` version with [npm overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides),\n  [pnpm overrides](https://pnpm.io/package_json#pnpmoverrides), or [yarn resolutions](https://yarnpkg.com/configuration/manifest#resolutions),\n- if nothing else helped, open an issue including the output of `npm ls @smithy/types` / `pnpm why @smithy/types` / `yarn why @smithy/types`.\n\n### AwsClientStub and strictFunctionTypes\n\nIf you need to explicitly type the mock variable,\nyou can use `AwsClientStub` type:\n\n```ts\nimport {AwsClientStub, mockClient} from 'aws-sdk-client-mock'\nimport {S3Client} from \"@aws-sdk/client-s3\";\n\nconst mock: AwsClientStub\u003cS3Client\u003e = mockClient(S3Client);\n```\n\nThe `AwsClientStub` type works only with `tsconfig` option\n`strictFunctionTypes=true` or (`strict=true`) in `tsconfig.json` file.\n\nSee details in [#167](https://github.com/m-radzikowski/aws-sdk-client-mock/issues/167).\n\n### Order of mock behaviors\n\nWider Command matchers must be declared first,\notherwise, they will take precedence over previous ones.\n\nIn this case, all `PublishCommand` sends will return message ID `222`:\n\n```typescript\nsnsMock\n  .on(PublishCommand, myInput).resolves({MessageId: '111'})\n  .on(PublishCommand).resolves({MessageId: '222'});\n```\n\nIf the order of the declarations is switched, sends with input matching `myInput`\nwill return ID `111` and all others `222`.\n\nIt works similarly with `onAnyCommand()`.\n\n### Order of type and instance mocks\n\nWhen you create both a Client type mock\nand a specific Client instance mock(s),\nyou need to declare type mock last.\nOtherwise, the other instances will not be mocked.\n\nRight now if you create a mock for the Client type,\nand then mock a specific instance of this Client,\nwith the order of mocking as here:\n\n```typescript\nconst sns1 = new SNSClient({}); // not mocked\n\nmockClient(SNSClient).resolves({MessageId: '123'});\n\nconst sns2 = new SNSClient({}); // mocked\nmockClient(sns2).resolves({MessageId: '456'});\n\nconst sns3 = new SNSClient({}); // not mocked\n```\n\nDeclaring mocks in this order will fix it:\n\n```typescript\nconst sns1 = new SNSClient({}); // mocked - default\n\nconst sns2 = new SNSClient({}); // mocked\nmockClient(sns2).resolves({MessageId: '456'});\n\nmockClient(SNSClient).resolves({MessageId: '123'});\n\nconst sns3 = new SNSClient({}); // mocked - default\n```\n\nPRs to fix this are welcome.\n\n### Using with Mocha\n\nWhen testing with Mocha, call `mockClient()`\nin the `beforeEach()` method, not in the global scope,\nto prevent overriding the mock between test files.\nSee [this](https://github.com/m-radzikowski/aws-sdk-client-mock/issues/64)\nfor more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-radzikowski%2Faws-sdk-client-mock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm-radzikowski%2Faws-sdk-client-mock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-radzikowski%2Faws-sdk-client-mock/lists"}