断言该方法已经在Mocha和Sinon的承诺中被调用

时间:2017-04-03 13:58:46

标签: javascript unit-testing promise mocha sinon

我有以下简化的方法和测试,我想测试handleResponse()的调用。

测试失败,handleResponse()根本没有被调用。如果我修改代码以在promise之外运行handleResponse,则测试成功完成。

这是因为承诺是异步的,并且断言是在承诺之前运行的吗?如果是这样,我怎么能在运行断言之前等待完成的承诺?

代码:

export function fetchList(id) {
  // handleResponse(response); // Works here

  return (dispatch) => {
    service.getList(id).then((response) => {
      handleResponse(response); // Doesnt work here
    }, (error) => {
      addNotification(error);
    });
  };
}

测试:

describe('fetchList', () => {
  let getListStub;
  let handleResponseStub;

  beforeEach(() => {
    getListStub = sinon.stub(service, 'getList');
    handleResponseStub = sinon.stub(appActions, 'handleResponse');
  });

  afterEach(() => {
    getListStub.restore();
    handleResponseStub.restore();
  });

  it('should dispatch handleResponse on success', () => {
    const dispatchStub = sinon.stub();
    const id = 1;
    const returnValue = 'return value';
    getListStub.withArgs(id).resolves(returnValue);

    listActions.fetchList(id)(dispatchStub);

    sinon.assert.calledOnce(getListStub);
    sinon.assert.calledOnce(handleResponseStub); // Fails
  });
});

1 个答案:

答案 0 :(得分:0)

您忘记将async/await添加到单元测试中并更改为return service.getList(...)。否则,断言将在解决service.getList(...)的承诺之前执行。

listActions.ts

import * as service from "./service";
import { handleResponse, addNotification } from "./appActions";

export function fetchList(id) {
  return dispatch => {
    return service.getList(id).then(
      response => {
        handleResponse(response);
      },
      error => {
        addNotification(error);
      }
    );
  };
}

appActions.ts

export function handleResponse(res) {
  console.log("handleResponse");
}

export function addNotification(error) {
  console.log("addNotification");
}

service.ts

export function getList(id) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve([]);
    }, 5000);
  });
}

listActions.spec.ts

import * as service from "./service";
import * as appActions from "./appActions";
import * as listActions from "./listActions";
import sinon from "sinon";

describe("fetchList", () => {
  let getListStub;
  let handleResponseStub;

  beforeEach(() => {
    getListStub = sinon.stub(service, "getList");
    handleResponseStub = sinon.stub(appActions, "handleResponse");
  });

  afterEach(() => {
    getListStub.restore();
    handleResponseStub.restore();
  });

  it("should dispatch handleResponse on success", async () => {
    const dispatchStub = sinon.stub();
    const id = 1;
    const returnValue = "return value";
    getListStub.withArgs(id).resolves(returnValue);

    await listActions.fetchList(id)(dispatchStub);

    sinon.assert.calledOnce(getListStub);
    sinon.assert.notCalled(dispatchStub);
    sinon.assert.calledOnce(handleResponseStub); // Fails
  });
});

带有覆盖率报告的单元测试结果:

  fetchList
    ✓ should dispatch handleResponse on success


  1 passing (95ms)

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |    83.33 |      100 |    53.85 |    82.86 |                   |
 appActions.ts       |       50 |      100 |        0 |       50 |               2,6 |
 listActions.spec.ts |      100 |      100 |      100 |      100 |                   |
 listActions.ts      |    85.71 |      100 |       75 |    85.71 |                11 |
 service.ts          |       25 |      100 |        0 |       25 |             2,3,4 |
---------------------|----------|----------|----------|----------|-------------------|

源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/43186634