Search code examples
typescriptmocha.jstddchaisinon

How to stub a static function in an abstract class | typescript


Im having a real trouble testing this function Client.read.pk(string).sk(string). I created this class to ease the process of working with dynamoDB's sdk, yet when i want to unit test this method im just cant seem to stab it! thank you so much for the help!

Code:

export abstract class Client {
  static read = {
    pk: (pk: string) => {
      return {
        sk: async (sk: string) => {
          return await new DocumentClient()
            .get({
              TableName: "TodoApp",
              Key: {
                PK: pk,
                SK: sk,
              },
            })
            .promise();
        },
      };
    },
  };
}

Solution

  • Since Sinon doesn't support stub standalone function and class constructor(DocumentClient class) imported from a module, you need to use link seams. we will be using proxyquire to construct our seams.

    E.g.

    Client.ts:

    import { DocumentClient } from 'aws-sdk/clients/dynamodb';
    
    export abstract class Client {
      static read = {
        pk: (pk: string) => {
          return {
            sk: async (sk: string) => {
              return await new DocumentClient()
                .get({
                  TableName: 'TodoApp',
                  Key: {
                    PK: pk,
                    SK: sk,
                  },
                })
                .promise();
            },
          };
        },
      };
    }
    

    Client.test.ts:

    import proxyquire from 'proxyquire';
    import sinon from 'sinon';
    
    describe('68430781', () => {
      it('should pass', async () => {
        const documentClientInstanceStub = {
          get: sinon.stub().returnsThis(),
          promise: sinon.stub().resolves('mocked data'),
        };
        const DocumentClientStub = sinon.stub().callsFake(() => documentClientInstanceStub);
        const { Client } = proxyquire('./Client', {
          'aws-sdk/clients/dynamodb': { DocumentClient: DocumentClientStub },
        });
        const actual = await Client.read.pk('a').sk('b');
        sinon.assert.match(actual, 'mocked data');
        sinon.assert.calledOnce(DocumentClientStub);
        sinon.assert.calledWithExactly(documentClientInstanceStub.get, {
          TableName: 'TodoApp',
          Key: {
            PK: 'a',
            SK: 'b',
          },
        });
        sinon.assert.calledOnce(documentClientInstanceStub.promise);
      });
    });
    

    unit test result:

      68430781
        ✓ should pass (435ms)
    
    
      1 passing (439ms)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |     100 |      100 |     100 |     100 |                   
     Client.ts |     100 |      100 |     100 |     100 |                   
    -----------|---------|----------|---------|---------|-------------------