Mocha - 测试 Promise,“完成”永远不会在 Promise 中被调用
Mocha - Testing Promise, `done` never gets called in 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 运行 我的测试;柴和诗乃.
我几个小时后终于解决了这个问题。看起来 then
块没有被调用,因为 xhr
.
引发了异常
让我详细说明。我正在使用 sinon 的 FakeXMLHttpRequest
,像这样:
var requests, xhr;
beforeEach(() => {
requests = [];
xhr = sinon.useFakeXMLHttpRequest();
xhr.onCreate = (req) => {
req.setResponseHeaders({ /* */ });
requests.push(req);
}
});
通过在 catch
块上放置一个 console.log
,我发现我得到的错误是 INVALID_STATE_ERR EXCEPTION 0
。这使我得出结论,xhr
一直是问题所在。
然后我发现了关于sinon的fakeServer
,并用它代替(但我不认为这实际上是解决这个问题的方法) .不是很相关,但我在这里也使用了 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);
});
});
我也有这个问题,原因是在连接打开之前试图响应 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,尽管它的名字,更像 "on request"。
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
}
结果是您必须在调用运行 XMLHttpRequest
的 send
的方法后放置您的响应代码,如:
myObject.get("testurl");
this.requests[0].respond(200, null, "");
我用的是respond
方法,但是setResponseHeaders
也是一样(respond
调用setResponseHeaders
)--在你的测试中调用的太早了.
我正在尝试测试将在承诺的 .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 运行 我的测试;柴和诗乃.
我几个小时后终于解决了这个问题。看起来 then
块没有被调用,因为 xhr
.
让我详细说明。我正在使用 sinon 的 FakeXMLHttpRequest
,像这样:
var requests, xhr;
beforeEach(() => {
requests = [];
xhr = sinon.useFakeXMLHttpRequest();
xhr.onCreate = (req) => {
req.setResponseHeaders({ /* */ });
requests.push(req);
}
});
通过在 catch
块上放置一个 console.log
,我发现我得到的错误是 INVALID_STATE_ERR EXCEPTION 0
。这使我得出结论,xhr
一直是问题所在。
然后我发现了关于sinon的fakeServer
,并用它代替(但我不认为这实际上是解决这个问题的方法) .不是很相关,但我在这里也使用了 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);
});
});
我也有这个问题,原因是在连接打开之前试图响应 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,尽管它的名字,更像 "on request"。
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
}
结果是您必须在调用运行 XMLHttpRequest
的 send
的方法后放置您的响应代码,如:
myObject.get("testurl");
this.requests[0].respond(200, null, "");
我用的是respond
方法,但是setResponseHeaders
也是一样(respond
调用setResponseHeaders
)--在你的测试中调用的太早了.