aws-sdk-client-mock

repository·main·Indexed 21 days ago

https://github.com/m-radzikowski/aws-sdk-client-mock

A library for mocking AWS SDK v3 Clients in unit tests, featuring a fluent, fully-typed interface. It allows developers to define mock behaviors based on Command types and input payloads, spy on sent commands, and verify interactions. The package includes aws-sdk-client-mock-jest for custom Jest and Vitest matchers to simplify assertions. It is the library recommended by the AWS SDK for JavaScript team.

Tokens
8.1K
Snippets
24
Records
32
Agent score
70%

What's inside aws-sdk-client-mock

  1. Overview of aws-sdk-client-mock

    main
    The aws-sdk-client-mock library provides a fluent, fully-typed interface for mocking AWS SDK v3 Clients. It allows you to define mock behaviors based on the Command type and/or its input payload, spy on sent commands, and verify interactions using Jest matchers. It is the library recommended by the AWS SDK for JavaScript team.
  2. Install and use AWS SDK v3 Client mock Jest matchers

    main

    The aws-sdk-client-mock-jest package provides custom Jest matchers to simplify testing when using aws-sdk-client-mock. These matchers allow you to write more expressive assertions when verifying that AWS SDK clients were called with specific parameters or returned specific results.

    For detailed usage instructions, refer to the main package documentation.

  3. Manage the order of type and instance mocks

    main

    If you are mocking both a Client type (the class) and specific Client instances, you must declare the type mock last. If you declare the type mock first, it may prevent specific instances from being correctly mocked.

    Correct Pattern:

    1. Create/Mock specific instances first.
    2. Declare the mockClient(ClientClass) (the type mock) last.
    const sns1 = new SNSClient({}); // mocked - default
    
    const sns2 = new SNSClient({}); // mocked
    mockClient(sns2).resolves({MessageId: '456'});
    
    // Declare type mock LAST
    mockClient(SNSClient).resolves({MessageId: '123'});
    
    const sns3 = new SNSClient({}); // mocked - default
  4. Manage the order of mock behaviors

    main

    When defining multiple behaviors for the same command, the order of declaration matters. Wider Command matchers must be declared first. If a more specific matcher is declared before a wider one, the wider one will take precedence and override the specific behavior.

    Example of correct ordering (Specific after Wide):

    snsMock
      .on(PublishCommand, myInput).resolves({MessageId: '111'})
      .on(PublishCommand).resolves({MessageId: '222'});

    If you switch the order, all calls (including those matching myInput) will return the behavior defined by the wider matcher.

  5. Use custom Jest matchers for AWS SDK mocks

    main

    The aws-sdk-client-mock-jest package provides custom matchers to simplify verifying that commands were sent.

    Installation:

    npm install -D aws-sdk-client-mock-jest

    Usage:

    import 'aws-sdk-client-mock-jest';
    
    // Verify a command was sent
    expect(snsMock).toHaveReceivedCommand(PublishCommand);
    
    // Verify command count
    expect(snsMock).toHaveReceivedCommandTimes(PublishCommand, 2);
    
    // Verify command with specific payload
    expect(snsMock).toHaveReceivedCommandWith(PublishCommand, { Message: 'hello world' });
    
    // Verify command with partial payload matching
    expect(snsMock).toHaveReceivedCommandWith(PublishCommand, { Message: expect.stringContaining('hello') });
    
    // Verify the Nth specific command
    expect(snsMock).toHaveReceivedNthCommandWith(2, PublishCommand, { Message: 'hello world' });

    Note: Shorter aliases like toReceiveCommandTimes() are also available.

    import 'aws-sdk-client-mock-jest';
    
    // a PublishCommand was sent to SNS
    expect(snsMock).toHaveReceivedCommand(PublishCommand);
    
    // at least one command was sent to SNS
    expect(snsMock).toHaveReceivedAnyCommand();
    
    // two PublishCommands were sent to SNS
    expect(snsMock).toHaveReceivedCommandTimes(PublishCommand, 2);
    
    // a PublishCommand with Message "hello world" was sent to SNS
    expect(snsMock).toHaveReceivedCommandWith(
        PublishCommand, {Message: 'hello world'}
    );
    
    // a PublishCommand with Message containing "hello" was sent to SNS
    expect(snsMock).toHaveReceivedCommandWith(
        PublishCommand, {Message: expect.stringContaining('hello')}
    );
    
    // the second PublishCommand sent to SNS was a PublishCommand with Message "hello world"
    expect(snsMock).toHaveReceivedNthCommandWith(
        2, PublishCommand, {Message: 'hello world'}
    );
    
    // the second PublishCommand sent to SNS had Message "hello world"
    expect(snsMock).toHaveReceivedNthSpecificCommandWith(
        2, PublishCommand, {Message: 'hello world'}
    );
  6. Use custom Vitest matchers for AWS SDK mocks

    main

    To use the matchers with Vitest, import the Vitest-specific entry point.

    import 'aws-sdk-client-mock-jest/vitest';
    import { expect } from 'vitest';
    
    // a PublishCommand was sent to SNS
    expect(snsMock).toHaveReceivedCommand(PublishCommand);
    import 'aws-sdk-client-mock-jest/vitest';
    import { expect } from 'vitest';
    
    // a PublishCommand was sent to SNS
    expect(snsMock).toHaveReceivedCommand(PublishCommand);
  7. Install aws-sdk-client-mock

    main

    Install the package as a development dependency using npm.

    Version Compatibility:

    @aws-sdk/*aws-sdk-client-mock
    ≥ 3.363.0≥ 3.x
    < 3.363.02.x

    If you encounter type errors like Argument of type 'typeof SomeClient' is not assignable to parameter of type..., ensure your versions match the table above.

    npm install -D aws-sdk-client-mock
  8. Configure AWS Client behavior with AwsStub

    main

    The AwsStub class is a wrapper around the mocked Client#send() method. It allows you to define how the client responds to different commands. You can set global behaviors for any command or specific behaviors for particular command types and inputs.

    Key capabilities:

    • Global behavior: Use .resolves(), .rejects(), or .callsFake() to define a default response for any command sent through the client.
    • Command-specific behavior: Use .on(CommandType, input) to target a specific AWS command and its input parameters.
    • Sequential responses: Use *Once methods (e.g., .resolvesOnce(), .rejectsOnce(), .callsFakeOnce()) to return different values for successive calls.
    // Example of setting up a mock and defining behaviors
    import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
    import { mockClient } from 'aws-sdk-client-mock';
    
    const snsMock = mockClient(SNSClient);
    
    // 1. Global behavior for any command
    snsMock.resolves({ MessageId: 'default-id' });
    
    // 2. Specific behavior for a command type and input
    snsMock
      .on(PublishCommand, { Message: 'My message' })
      .resolves({ MessageId: '111' });
    
    // 3. Sequential behavior
    snsMock
      .resolvesOnce({ MessageId: 'first-call' })
      .resolvesOnce({ MessageId: 'second-call' })
      .resolves({ MessageId: 'default' });