简体   繁体   English

Mocha-测试Promise,在Promise中永远不会调用“ done”

[英]Mocha - Testing Promise, `done` never gets called in Promise

I'm trying to test a spy that would be called in the .then block of a promise, but the done in the then block doesn't seem to be executed at all. 我正在尝试测试将在promise的.then块中调用的间谍,但是then块中的done似乎根本没有执行。

I'm getting timeout of 2000ms exceeded. 我的timeout of 2000ms exceeded.

Here's what I'm testing (async): 这是我正在测试的(异步):

/**
 * 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;
      })
  }
}

Here's my test: 这是我的测试:

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);
  });
});

I'm using Karma to run my tests; 我正在使用Karma进行测试; Chai and Sinon. 柴和诗乃

I also had this issue, the cause was trying to respond to the XHR before the connection was opened, eg 我也有这个问题,原因是尝试在连接打开之前尝试响应XHR,例如

This code will throw INVALID_STATE_ERR - 0 from FakeXMLHttpRequest.setResponseHeaders : 此代码将从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");
  });

});

This code works: 此代码有效:

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, "");
  });

});

Reading the documentation, which itself does show the same technique of pushing to a requests array, I had subconsciously and inaccurately came away with the impression that onCreate, despite its name, was more like "on request". 阅读文档时,它的确显示了相同的推送到请求数组的技术,我下意识和不准确地发现,尽管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 
}

The result is that you have to put your respond code after you call the method that runs XMLHttpRequest 's send , as: 结果是,您必须在调用运行XMLHttpRequestsend方法的方法之后放入响应代码,如下所示:

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

I was using the respond method, but the same is true for setResponseHeaders ( respond calls setResponseHeaders )--in your test it was called too early. 我用的respond方法,但相同的是真正的setResponseHeadersrespond电话setResponseHeaders ) -在测试中,它被称为太早。

I've finally solved this issue after hours. 几个小时后,我终于解决了这个问题。 It looks like the then block wasn't being called because an exception was being thrown due to xhr . 似乎未调用then块,因为xhr引发了异常。

Let me elaborate. 让我详细说明。 I was using sinon 's FakeXMLHttpRequest , like so: 我正在使用sinonFakeXMLHttpRequest ,如下所示:

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

By putting a console.log on the catch block, I found out that I was getting the error was INVALID_STATE_ERR EXCEPTION 0 . 通过将console.log放在catch块上,我发现我得到的错误是INVALID_STATE_ERR EXCEPTION 0 This leads me to the conclusion that xhr was the problem all along. 这使我得出结论, xhr一直是问题所在。

And then I found out about sinon 's fakeServer , and used it instead (but I don't think this is actually the solution to this problem). 然后,我发现了sinonfakeServer ,并使用了它(但我不认为这实际上是解决此问题的方法)。 Not really related, but I also used sandbox here because saved me from writing countless of .restore for stubs, etc. 并没有真正的关系,但是我在这里也使用了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);
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM