【问题标题】:Mocha: Ensure the done() callback is being called in this testMocha:确保在此测试中调用了 done() 回调
【发布时间】:2017-03-12 09:18:46
【问题描述】:

我使用axios 编写了一个小型拦截器,它将清除localBrowserStorage,如果响应代码为401,则将用户重定向到登录页面。 它工作正常,但我在单元测试中遇到了一些错误。

测试

describe('Api Service', () => {
  let sandbox;

  beforeEach(() => {
    moxios.install();
    sandbox = sinon.sandbox.create();
  });

  afterEach(() => {
    moxios.uninstall();
    sandbox.restore();
  });

  describe.only('interceptors', () => {
    it('clear storage and redirect to login if response status code is 401', (done) => {
      moxios.withMock(() => {
        sandbox.spy(browserHistory, 'push');
        sandbox.spy(storage, 'clear');

        axios.get('/test');

        moxios.wait(() => {
          const request = moxios.requests.mostRecent();
          request.respondWith({
            status: 401,
            response: {}
          }).then(() => {
            expect(browserHistory.push).to.have.been.calledWith('/login');
            expect(storage.clear).to.have.been.called; // eslint-disable-line no-unused-expressions
            done();
          });
        });
      });
    });
  });
});

我收到这两个警告:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Request failed with status code 401
(node:5338) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): AssertionError: expected push to have been called with arguments /login

还有这个错误:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

编辑:

axios.interceptors.response.use((response) => {
  if (response.status === 401) {
    storage.clear();
    browserHistory.push('/login');
    return response;
  }
  return response;
});

【问题讨论】:

    标签: unit-testing http mocha.js sinon axios


    【解决方案1】:

    您需要通过在 catch 处理程序中调用 done 将拒绝传递回 Mocha:

    request.respondWith({
      status: 401,
      response: {}
    }).then(() => {
      expect(browserHistory.push).to.have.been.calledWith('/login');
      expect(storage.clear).to.have.been.called; // eslint-disable-line no-unused-expressions
      done();
    }).catch(done);
    

    如果您不处理被拒绝的承诺,done 有可能永远不会被调用(导致超时)。

    例如,如果其中一个期望失败,它将引发错误。发生这种情况时,在期望行之后对done 的调用将永远不会被执行。如上所述,您可以(并且应该)使用 .catch 子句捕获错误。那应该调用 done 并出现错误。我使用的代码是:

    .catch(function(err) {
      done(err);
    })
    

    【讨论】:

    • 您能否再解释一下,以便我完全理解这一点以供将来参考?此外,按照您所说的做不会调用spies 并且测试失败。有什么建议吗?
    • 它仍然会抛出一个UnhandledPromiseRejectionWarning
    • @Umair 是哪一个?
    • 我已经用我实际测试的代码更新了问题。在您在答案中指定之后,测试失败并抛出一个错误,指出它没有调用browserHistory.pushstorage.clear。此外,警告(node:5935) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Request failed with status code 401 不会消失。
    • @Umair 所以你的测试失败了,因为你的期望失败了。这就是测试的目的。我不确定你为什么得到UnhandledPromiseRejectionWarning;我以为它会被request.respondWith() 抛出,但也许不是。我不知道moxios,所以可能与此有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    相关资源
    最近更新 更多