2015-01-30 11 views
12

Sto provando a scrivere un test unitario con Jest e Jasmine-pit per il codice qui sotto e sono totalmente confuso con esso. Il codice è una chiamata Ajax che recupera alcuni dati dalla risorsa e li salva nella variabile.Come scrivere un test unitario con Jest per il codice con Promise

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

commento indipendenti (avete già la risposta): [differita è un modello anti] (https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns), non lo fanno usali :). –

risposta

9

Questo mi ha frustrato gran parte della giornata di oggi. Ecco cosa ho ottenuto (testando il mio ActionCreator (Flux) che utilizza un'API che restituisce promesse e invia roba basata sulla promessa). Fondamentalmente metto a punto il metodo API che restituisce la promessa e la risolve subito. Penseresti che questo sarebbe sufficiente per ottenere i .then (...) metodi per sparare, ma il codice del pit era necessario per far funzionare il mio ActionCreator in base alla promessa risolta.

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

Ecco l'ActionCreator che lega l'API per il 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;