【问题标题】:Mocha - Testing Promise, `done` never gets called in PromiseMocha - 测试 Promise,`done` 永远不会在 Promise 中被调用
【发布时间】:2015-06-30 21:36:37
【问题描述】:

我正在尝试测试将在 promise 的 .then 块中调用的间谍,但 then 块中的 done 似乎根本没有执行。

我收到timeout of 2000ms exceeded.

这是我正在测试的内容(异步):

/**
 * Passed down to the LoginForm component to
 * handle form submission.
 */
_submitHandler(data) {
  return function(evt) {
    evt.preventDefault && evt.preventDefault();
    evt.stopPropagation && evt.stopPropagation();

    return request('post', 'auth', data)
      .then((res) => {
        AuthActions.login();
        return res;
      })
  }
}

这是我的测试:

describe('when it succeeds', () => {
  it('should login', (done) => {
    sinon.spy(AuthActions, 'login');

    Instance._submitHandler({})({})
      .then((res) => {
        console.log('Called!!!');
        expect(AuthActions.login.called).to.equal(true);
        AuthActions.login.restore();
        done();
      }, done);
  });
});

我正在使用 Karma 运行我的测试;柴和诗乃。

【问题讨论】:

  • 你得到什么失败信息?

标签: javascript unit-testing promise mocha.js


【解决方案1】:

我也有这个问题,原因是在打开连接之前尝试响应 XHR,例如

此代码将从FakeXMLHttpRequest.setResponseHeaders 抛出INVALID_STATE_ERR - 0

describe("get", function () {

  beforeEach(function () {
    this.xhr = sinon.useFakeXMLHttpRequest();
    this.xhr.onCreate = function (request) {
      request.respond(200, null, "");
    };
  });

  afterEach(function () {
    this.xhr.restore();
  });

  it("should make a request", function () {
    myObject.get("testurl");
  });

});

此代码有效:

describe("get", function () {

  beforeEach(function () {
    this.xhr = sinon.useFakeXMLHttpRequest();
    this.requests = [];
    this.xhr.onCreate = function (request) {
      this.requests.push(request);
    };
  });

  afterEach(function () {
    this.xhr.restore();
  });

  it("should make a request", function () {
    myObject.get("testurl");
    this.requests[0].respond(200, null, "");
  });

});

阅读文档,它本身确实展示了推送到请求数组的相同技术,我下意识地且不准确地得出这样的印象,即 onCreate,尽管它的名字,更像是“请求”。

myObject.get = function (url) {
  var http = new XMLHttpRequest(); 
  // the XHR instance exists
  // readyState is 0
  // onCreate runs now
  http.open("GET", url); 
  http.send(); 
  // readyState is 1
  // can call setResponseHeaders and respond 
}

结果是你必须在调用运行XMLHttpRequestsend的方法之后放入你的响应代码,如:

myObject.get("testurl");
this.requests[0].respond(200, null, "");

我使用的是respond 方法,但setResponseHeadersrespond 调用setResponseHeaders)也是如此——在您的测试中,它被调用得太早了。

【讨论】:

    【解决方案2】:

    几个小时后我终于解决了这个问题。看起来then 块没有被调用,因为xhr 引发了异常。

    让我详细说明。我用的是sinonFakeXMLHttpRequest,像这样:

    var requests, xhr;
    beforeEach(() => {
      requests = [];
      xhr = sinon.useFakeXMLHttpRequest();
      xhr.onCreate = (req) => {
        req.setResponseHeaders({ /* */ });
        requests.push(req);
      }
    });
    

    通过将console.log 放在catch 块上,我发现我收到的错误是INVALID_STATE_ERR EXCEPTION 0。这使我得出结论,xhr 一直是问题所在。

    然后我发现了sinonfakeServer,并改用它(但我不认为这实际上是解决这个问题的方法)。不是很相关,但我在这里也使用了sandbox,因为我不用为存根等写无数的.restore

    describe('when it succeeds', () => {
      var sandbox, server, Instance;
      beforeEach(() => {
        sandbox = sinon.sandbox.create();
        sandbox.useFakeServer();
        server = sandbox.server;
        server.respondWith([200, { "Content-Type": "application/json" }, JSON.stringify({ data: { token: '' }})]);
        sandbox.spy(AuthActions, 'login');
        Instance = TestUtils.renderIntoDocument(<Component />);
      });
      afterEach(() => {
        sandbox.restore();
      });
      it('should login', (done) => {
        Instance._submitHandler({})({})
          .then(() => {
            expect(AuthActions.login.called).to.equal(true);
            done();
          }, done);
    
        setTimeout(() => {
          server.respond();
        }, 0);
      });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-30
      • 2017-04-08
      • 2015-02-17
      • 2018-01-16
      • 1970-01-01
      • 2019-02-04
      • 2015-07-16
      • 1970-01-01
      相关资源
      最近更新 更多