Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typings mismatches between client mock and AWS typings #246

Open
1 task done
rganatra-kasada opened this issue Nov 21, 2024 · 4 comments
Open
1 task done

Typings mismatches between client mock and AWS typings #246

rganatra-kasada opened this issue Nov 21, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@rganatra-kasada
Copy link

Checklist

  • I have read Caveats documentation and didn't find a solution for this problem there.

Bug description

Hello 👋 !

I'm having troubles with typings mismatches between the AWS client mocks vs the AWS client typings themselves, even after trying out everything in the caveats docs.

I'm currently using an AthenaClient and a GlueClient in my code and passing a mock for either to a function which expects the respective clients shows me typings errors like:

Argument of type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, AthenaClientResolvedConfig>' is not assignable to parameter of type 'AthenaClient'.
  Type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, AthenaClientResolvedConfig>' is missing the following properties from type 'AthenaClient': config, destroy, middlewareStackts(2345)

and

Argument of type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, GlueClientResolvedConfig>' is not assignable to parameter of type 'GlueClient'.
  Type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, GlueClientResolvedConfig>' is missing the following properties from type 'GlueClient': config, destroy, middlewareStackts(2345)

The specific package versions I'm using:

{
  "version": "0.0.0",
  "main": "./dist/src/index.js",
  "private": true,
  "license": "UNLICENSED",
  "engines": {
    "node": ">=20"
  },
  "scripts": {
    "build": "tsc -p tsconfig.build.json",
    "build:watch": "yarn build --watch",
    "clean": "rm -fr dist",
    "clean:full": "yarn run clean; rm -fr .task node_modules",
    "start": "node dist/src/index.js",
    "test": "jest -c ./jest.config.js"
  },
  "devDependencies": {
    "@types/jest": "29.5.14",
    "@types/node": "22.8.4",
    "aws-sdk-client-mock": "4.1.0",
    "aws-sdk-client-mock-jest": "4.1.0",
    "jest": "29.7.0",
    "jest-extended": "4.0.2",
    "ts-jest": "29.2.5",
    "typescript": "5.6.2"
  },
  "dependencies": {
    "@aws-sdk/client-athena": "3.696.0",
    "@aws-sdk/client-glue": "3.696.0",
    "tslib": "2.7.0"
  }
}

I've also verified that I have only one version of @smithy/types at the moment:

$  yarn why @smithy/types
yarn why v1.22.22
[1/4] Why do we have the module "@smithy/types"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "@smithy/types@3.7.1"
info Reasons this module exists
   - "@aws-sdk#client-athena" depends on it
   - Hoisted from "@aws-sdk#client-athena#@smithy#types"
   - Hoisted from "@aws-sdk#client-glue#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#client-sso-oidc#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#client-sts#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#core#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-bucket-endpoint#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-expect-continue#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-flexible-checksums#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#middleware-host-header#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-location-constraint#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#middleware-logger#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#middleware-recursion-detection#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-sdk-s3#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#middleware-ssec#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#middleware-user-agent#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#region-config-resolver#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#signature-v4-multi-region#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#types#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#util-endpoints#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#util-user-agent-browser#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#util-user-agent-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@aws-sdk#xml-builder#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#config-resolver#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#core#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#eventstream-serde-browser#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#eventstream-serde-config-resolver#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#eventstream-serde-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#fetch-http-handler#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#hash-blob-browser#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#hash-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#hash-stream-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#invalid-dependency#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#md5-js#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-content-length#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-endpoint#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-retry#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-serde#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-stack#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#node-config-provider#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#node-http-handler#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#protocol-http#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#smithy-client#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#url-parser#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#util-defaults-mode-browser#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#util-defaults-mode-node#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#util-endpoints#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#util-middleware#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#util-retry#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#util-stream#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#util-waiter#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-env#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-http#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-ini#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-process#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-sso#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-web-identity#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#node-http-handler#@smithy#abort-controller#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@smithy#credential-provider-imds#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#eventstream-serde-browser#@smithy#eventstream-serde-universal#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#node-config-provider#@smithy#property-provider#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#fetch-http-handler#@smithy#querystring-builder#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#url-parser#@smithy#querystring-parser#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@smithy#middleware-retry#@smithy#service-error-classification#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@smithy#shared-ini-file-loader#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#core#@smithy#signature-v4#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-sso#@aws-sdk#client-sso#@smithy#types"
   - Hoisted from "@aws-sdk#client-athena#@aws-sdk#credential-provider-node#@aws-sdk#credential-provider-sso#@aws-sdk#token-providers#@smithy#types"
   - Hoisted from "@aws-sdk#client-s3#@smithy#eventstream-serde-browser#@smithy#eventstream-serde-universal#@smithy#eventstream-codec#@smithy#types"
info Disk size without dependencies: "1.43MB"
info Disk size with unique dependencies: "1.55MB"
info Disk size with transitive dependencies: "1.55MB"
info Number of shared dependencies: 1
Done in 0.32s.

Any help would be appreciated, thank you!

Reproduction

import { GlueClient } from '@aws-sdk/client-glue';
import { mockClient } from 'aws-sdk-client-mock';

const listTables = async (client: GlueClient, databaseName: string) => new Error('test');

describe('listTables', () => {
  describe('when the get-tables command fails', () => {
    it('should return an error', async () => {
      const client = mockClient(new GlueClient());

      client.onAnyCommand().rejects('mock rejection');

      // The `client` here shows a typings error:
      // Argument of type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, GlueClientResolvedConfig>' is not assignable to parameter of type 'GlueClient'.
      //  Type 'AwsStub<ServiceInputTypes, ServiceOutputTypes, GlueClientResolvedConfig>' is missing the following properties from type 'GlueClient': config, destroy, middlewareStackts(2345)
      const result = await listTables(client, 'some_database');

      expect(result).toBeInstanceOf(Error);
    });
  });
});


### Environment

- Node version: `22.11.0`
- Testing lib and version: `jest@29.7.0`
- Typescript version: `5.6.2`
- AWS SDK v3 Client mock version: `4.1.0`
- AWS JS SDK libs and versions:
    - `@aws-sdk/client-athena`: `3.696.0`
    - `@aws-sdk/client-glue`:  `3.696.0`
@tylerd-canva
Copy link

Seeing the same thing. I worked around this by not passing the mocks into the methods.

Before

const mockECS = mockClient(ECSClient);

mockECS.on(DescribeTaskDefinitionCommand).resolves({
  taskDefinition: ...,
});

const result = await getTemplateTaskDefinition(mockECS, accountId);

After

const mockECS = mockClient(ECSClient);

mockECS.on(DescribeTaskDefinitionCommand).resolves({
  taskDefinition: mockTaskDefinition,
});

const result = await getTemplateTaskDefinition(new ECSClient({}), accountId);

Works the same but passes TSC.

@rganatra-kasada
Copy link
Author

@tylerd-canva Thank you, that worked! I still feel the typings mismatch is an issue but I'm happy to close this issue for now since there's a viable workaround.

@tylerd-canva
Copy link

Personally I'd leave it open as I'd much prefer the approach we both tried initially :P

@rganatra-kasada
Copy link
Author

I spoke to soon! The workaround certainly works for scenarios where only one instance of a client is needed in a set of tests, but not when more than one are needed. I'll leave it open in that case since the original approach serves a valid purpose.

Personally I'd leave it open as I'd much prefer the approach we both tried initially :P

I'm with you on that one 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants