最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to write a unit test with Jest for code with Promise - Stack Overflow

programmeradmin1浏览0评论

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.

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

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.

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;
},
Share Improve this question asked Jan 30, 2015 at 15:41 mu_samu_sa 2,72510 gold badges42 silver badges58 bronze badges 1
  • Unrelated ment (you already have your answer): deferred is an anti pattern, don't use them :). – Quentin Roy Commented Jun 13, 2016 at 9:45
Add a ment  | 

2 Answers 2

Reset to default 9

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.

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:

'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; 

This tutorial on the website of Jest doesn't answer the question directly, but has the gist of how to unit test promise.

https://facebook.github.io/jest/docs/tutorial-async.html

发布评论

评论列表(0)

  1. 暂无评论