返回promise的jasmine测试函数

时间:2015-12-28 14:55:38

标签: javascript unit-testing jasmine tdd promise

我有以下功能实现

function getRepo(url) {
    var repos = {};

    if (repos.hasOwnProperty(url)) {
        return repos[url];
    }

    return $.get(url)
        .then(repoRetrieved)
        .fail(failureHandler);

    function repoRetrieved(data) {

        return repos[url] = data;
    }

    function failureHandler(err, xhr) {
        throw new Error(xhr.responseText);
    }
}

我写了以下测试:

describe('"getRepo" method', function() {
    var getDeffered;
    var $;

     beforeEach(function() {
         getDeffered = Q.defer();
         $ = jasmine.createSpyObj('$', ['get']);
         $.get.and.returnValue(getDeffered.promise);
     });

     it('should return a promise', function(){
         expect(getRepo('someURL')).toEqual(getDeffered.promise);
     });

});

此测试失败。我想是因为我称之为then方法。

如果函数实现是:

,它不会失败
function getRepo(url) {
    return $.get(url);
}

这是使用Q.defer()

时jasmine抛出的消息
Expected { promiseDispatch : Function, valueOf : Function, inspect : Function }
to equal { promiseDispatch : Function, valueOf : Function, inspect : Function }.

如果我使用jQuery Deferred:

,这就是消息
Expected { state : Function, always : Function, then : Function, promise : Function, pipe : Function, done : Function, fail : Function, progress : Function } 
to equal { state : Function, always : Function, then : Function, promise : Function, pipe : Function, done : Function, fail : Function, progress : Function }.

jQuery延期测试实现:

describe('"getRepo" method', function() {
    var getDeffered;
    var $;

    beforeEach(function() {
        getDeffered = real$.Deferred();
        $ = jasmine.createSpyObj('$', ['get']);
        $.get.and.returnValue(getDeffered.promise());
    });

    it('should return a promise', function(){
        expect(getRepo('someURL')).toEqual(getDeffered.promise());
    });

});

2 个答案:

答案 0 :(得分:1)

您可以直接测试已解析的值,而不是将返回的对象作为承诺进行测试,从而获得更准确的结果:

describe('"getRepo" method', function() {
    var originalGet;
    beforeAll(function() {
        originalGet = $.get;
    });
    beforeEach(function() {
        $.get = originalGet; // Restore original function
    });

    it('should update the data[] array when resolved', function(done) {
    // This is an asynchronous test, so we need to pass done    ^^^^
        var expectedResult = 'test data';
        $.get = function() { 
            var dfd = $.Deferred();
            dfd.resolve(expectedResult);
            return dfd.promise();
        };
        getRepo('someURL').then(function(repos) {
            var actualResult = repos['someUrl'];
            expect(actualResult).toEqual(expectedResult);
            done(); // This is an asynchronous test. We must mark the test as done.
        });
    });
});

请注意,jQuery的Promise实现非常糟糕。最好是使用本机Promises或像Bluebird这样的库。

答案 1 :(得分:0)

您正在创建一个本地$变量,然后为其分配一个间谍对象。这与$使用的getRepo不同。

您应该删除本地变量var $;并模拟原始$.get

试试这个:

describe('"getRepo" method', function() {
    var testPromise;

    beforeEach(function() {
        testPromise = real$.Deferred().promise();
        spyOn($, 'get').andCallFake(function() {
            return testPromise;
        });

    });

    it('should return a promise', function(){
        expect(getRepo('someURL')).toEqual(testPromise);
    });

});