我正在尝试使用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;
},
答案 0 :(得分:9)
今天大部分时间都让我感到沮丧。这是我最终得到的(测试我的ActionCreator(Flux),它使用一个API来返回promises并根据promise发送东西)。基本上我嘲笑返回promise的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});
});
});
});
以下是将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;
答案 1 :(得分:1)
Jest网站上的这个教程没有直接回答这个问题,但是有如何单元测试承诺的要点。