javascript 如何使用 Jest 为带有 Promise 的代码编写单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28239452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to write a unit test with Jest for code with Promise
提问by mu_sa
I am trying to write a unit test with Jest and Jasmine-pit for the below code and am totally stumped with it. The code is an ajax call which retrieves some data from resource and saves it in the variable.
我正在尝试使用 Jest 和 Jasmine-pit 为以下代码编写单元测试,并且完全被它难住了。该代码是一个 ajax 调用,它从资源中检索一些数据并将其保存在变量中。
init = function() {
var deferred = Q.defer();
$.ajax({
type: 'GET',
datatype: 'json',
url: window.location.origin + name,
success: function (data) {
userId = data.userId;
apiKey = data.apiKey;
deferred.resolve();
}
});
return deferred.promise;
},
回答by pherris
This frustrated me most of the day today. Here is what I ended up with (testing my ActionCreator (Flux) which uses an API that returns promises and dispatches stuff based on the promise). Basically I mock out the API method that returns the promise and resolve it right away. You'd think that this would be enough to get the .then(...) methods to fire, but the pit code was required to have my ActionCreator actually do work based on the resolved promise.
这让我今天大部分时间都感到沮丧。这是我最终得到的结果(测试我的 ActionCreator (Flux),它使用一个 API 返回承诺并根据承诺分派内容)。基本上我模拟了返回承诺并立即解决它的 API 方法。您可能认为这足以触发 .then(...) 方法,但是需要坑代码才能让我的 ActionCreator 基于已解决的承诺实际执行工作。
jest.dontMock('../LoginActionCreators.js');
jest.dontMock('rsvp'); //has to be above the require statement
var RSVP = require('rsvp'); //could be other promise library
describe('LoginActionCreator', function() {
pit('login: should call the login API', function() {
var loginActionCreator = require('../LoginActionCreators');
var Dispatcher = require('../../dispatcher/Dispatcher');
var userAPI = require('../../api/User');
var Constants = require('../../constants/Constants');
//my api method needs to return this
var successResponse = { body: {"auth_token":"Ve25Mk3JzZwep6AF7EBw=="} };
//mock out the API method and resolve the promise right away
var apiMock = jest.genMockFunction().mockImplementation(function() {
var promise = new RSVP.Promise(function(resolve, reject) {
resolve(successResponse);
});
return promise;
});
//my action creator will dispatch stuff based on the promise resolution, so let's mock that out too
var dispatcherMock = jest.genMockFunction();
userAPI.login = apiMock;
Dispatcher.dispatch = dispatcherMock;
var creds = {
username: 'username',
password: 'password'
};
//call the ActionCreator
loginActionCreator.login(creds.username, creds.password);
//the pit code seems to manage promises at a slightly higher level than I could get to on my
// own, the whole pit() and the below return statement seem like they shouldnt be necessary
// since the promise is already resolved in the mock when it is returned, but
// I could not get this to work without pit.
return (new RSVP.Promise(function(resolve) { resolve(); })).then(function() {
expect(apiMock).toBeCalledWith(creds);
expect(dispatcherMock.mock.calls.length).toBe(2);
expect(dispatcherMock.mock.calls[0][0]).toEqual({ actionType: Constants.api.user.LOGIN, queryParams: creds, response: Constants.request.PENDING});
expect(dispatcherMock.mock.calls[1][0]).toEqual({ actionType: Constants.api.user.LOGIN, queryParams: creds, response: successResponse});
});
});
});
Here is the ActionCreator which ties the API to the Dispatcher:
这是将 API 与 Dispatcher 联系起来的 ActionCreator:
'use strict';
var Dispatcher = require('../dispatcher/Dispatcher');
var Constants = require('../constants/Constants');
var UserAPI = require('../api/User');
function dispatch(key, response, params) {
var payload = {actionType: key, response: response};
if (params) {
payload.queryParams = params;
}
Dispatcher.dispatch(payload);
}
var LoginActionCreators = {
login: function(username, password) {
var params = {
username: username,
password: password
};
dispatch(Constants.api.user.LOGIN, Constants.request.PENDING, params);
var promise = UserAPI.login(params);
promise.then(function(res) {
dispatch(Constants.api.user.LOGIN, res, params);
}, function(err) {
dispatch(Constants.api.user.LOGIN, Constants.request.ERROR, params);
});
}
};
module.exports = LoginActionCreators;
回答by Xuan
This tutorial on the website of Jest doesn't answer the question directly, but has the gist of how to unit test promise.
Jest 网站上的这个教程没有直接回答问题,但是有如何单元测试 promise 的要点。