[英]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: 结果是,您必须在调用运行
XMLHttpRequest
的send
方法的方法之后放入响应代码,如下所示:
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
方法,但相同的是真正的setResponseHeaders
( respond
电话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: 我正在使用sinon的
FakeXMLHttpRequest
,如下所示:
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). 然后,我发现了sinon的
fakeServer
,并使用了它(但我不认为这实际上是解决此问题的方法)。 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.