typescript - How do I unit test the result of a 'then' of a promise in JavaScript? - Stack Overflow

I'm using TypeScript to write a very simple service that utilizes the AWS SDK. My Jest unit tests

I'm using TypeScript to write a very simple service that utilizes the AWS SDK. My Jest unit tests are passing, but the coverage reports are saying that the line 'return result.Items' is not covered. Can anyone tell why this is? Is it a bug in jest?

// service file

/**
 * Gets an array of documents.
 */
function list(tableName) {
  const params = {
    TableName: tableName,
  };
  return docClient
    .scan(params)
    .promise()
    .then((result) => {
      return result.Items;
    });
}

// test file

const stubAwsRequestWithFakeArrayReturn = () => {
  return {
    promise: () => {
      return { then: () => ({ Items: 'fake-value' }) };
    },
  };
};

it(`should call docClient.scan() at least once`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledTimes(1);
});

it(`should call docClient.scan() with the proper params`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledWith({
    TableName: 'fake-table',
  });
});

it('should return result.Items out of result', async () => {
  const mockAwsCall = jest
    .fn()
    .mockImplementation(stubAwsRequestWithFakeArrayReturn);
  aws.docClient.get = mockAwsCall;
  const returnValue = await db.get('fake-table', 'fake-id');
  expect(returnValue).toEqual({ Items: 'fake-value' });
});

I'm using TypeScript to write a very simple service that utilizes the AWS SDK. My Jest unit tests are passing, but the coverage reports are saying that the line 'return result.Items' is not covered. Can anyone tell why this is? Is it a bug in jest?

// service file

/**
 * Gets an array of documents.
 */
function list(tableName) {
  const params = {
    TableName: tableName,
  };
  return docClient
    .scan(params)
    .promise()
    .then((result) => {
      return result.Items;
    });
}

// test file

const stubAwsRequestWithFakeArrayReturn = () => {
  return {
    promise: () => {
      return { then: () => ({ Items: 'fake-value' }) };
    },
  };
};

it(`should call docClient.scan() at least once`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledTimes(1);
});

it(`should call docClient.scan() with the proper params`, () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  db.list('fake-table');
  expect(mockAwsCall).toBeCalledWith({
    TableName: 'fake-table',
  });
});

it('should return result.Items out of result', async () => {
  const mockAwsCall = jest
    .fn()
    .mockImplementation(stubAwsRequestWithFakeArrayReturn);
  aws.docClient.get = mockAwsCall;
  const returnValue = await db.get('fake-table', 'fake-id');
  expect(returnValue).toEqual({ Items: 'fake-value' });
});
Share Improve this question asked Feb 3, 2019 at 5:33 therealscifitherealscifi 3825 silver badges12 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

The line not covered is the success callback passed to then.

Your mock replaces then with a function that doesn't accept any parameters and just returns an object. The callback from your code is passed to the then mock during the test but it doesn't call the callback so Jest correctly reports that the callback is not covered by your tests.

Instead of trying to return a mock object that looks like a Promise, just return an actual resolved Promise from your mock:

const stubAwsRequestWithFakeArrayReturn = () => ({
  promise: () => Promise.resolve({ Items: 'fake-value' })
});

...that way then will still be the actual Promise.prototype.then and your callback will be called as expected.


You should also await the returned Promise to ensure that the callback has been called before the test pletes:

it(`should call docClient.scan() at least once`, async () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  await db.list('fake-table');  // await the Promise
  expect(mockAwsCall).toBeCalledTimes(1);
});

it(`should call docClient.scan() with the proper params`, async () => {
  const mockAwsCall = jest.fn().mockImplementation(stubAwsRequest);
  aws.docClient.scan = mockAwsCall;
  await db.list('fake-table');  // await the Promise
  expect(mockAwsCall).toBeCalledWith({
    TableName: 'fake-table',
  });
});

The Library chai-as-promised is worth looking at.

https://www.chaijs./plugins/chai-as-promised/

Instead of manually wiring up your expectations to a promise’s fulfilled and rejected handlers.

doSomethingAsync().then(
    function (result) {
        result.should.equal("foo");
        done();
    },
    function (err) {
       done(err);
    }
);

you can write code that expresses what you really mean:

return doSomethingAsync().should.eventually.equal("foo");

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745584826a4634471.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信