Angular Jasmine单元测试承诺

时间:2014-06-20 14:40:17

标签: javascript angularjs unit-testing jasmine

我想写一个单元测试,它只显示创建两个promises的行为,用$ q.all将它们包装成一个,然后测试promises是否同时被解析。

  describe("Application controller", function() {
    var scope;
    var controller;

    beforeEach(module('my.namespace'));
//this suite can be removed.
    describe("Application ", function() {
        beforeEach(
            inject(function ($rootScope, $controller,$q) {
                scope = $rootScope.$new();
                controller = $controller('Application', {
                    '$scope': scope
                });
            }));


        it("should package two promises into one", function (done) {
            inject(function ($rootScope) {
                setTimeout(function () {
                    $rootScope.$apply(function () {
                        var promiseOne = $q.defer(),
                            //promiseOneData;
                            promiseTwo = $q.defer();
                            //promiseTwoData
                        promiseOne.then(function(data){
                            promiseOne.resolve('promiseOne');
                            expect(1).toBe(1);
                        });
                        promiseTwo.then(function(data){
                            promiseTwoData.resolve('promiseTwo');
                        })
                        var allPromises = $q.all([promiseOne,promiseTwo]);
                        allPromises.then(function(data){
                            //data should contain an array of two empty elements for each promise
                            expect(data.length).toBe(2);
                        });
                        done();
                    });
                }, 1000);


    })
});

有了这个,我得到了错误:Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.我不想在这里实际使用get请求,我只需要两个promise来解决,然后转移到包含两者的一个promise中。我怎么能用Angular和茉莉花做到这一点?

2 个答案:

答案 0 :(得分:1)

你想要什么可能是一个间谍,看看它是否被召唤。

describe('test $q', function() {
  var
    $scope;
    $controller;
    $httpBackend;

  beforeEach(function() {
    module('myModule');
    inject(function(_$rootScope_, _$controller_) {
        $scope = _$rootScope_.$new();
        $controller = _$controller_;
        $controller ('MyCtrl', {
          $scope: $scope
        });
    });

  it('should test that $q.all calls callback when dependent promises are resolved', function() {
    var deferOne = $q.defer(),
        deferTwo = $q.defer();
        combinedSpy = jasmine.createSpy('combined');    

    $q.all([deferOne.promise, deferTwo.promise]).then(combinedSpy);

    expect(combinedSpy).toNotHaveBeenCalled();
    deferOne.resolve();
    deferTwo.resolve();
    $scope.apply();
    expect(combinedSpy).toHaveBeenCalled();
  });

这个测试标题非常令人困惑,你没有模拟承诺。你正在测试一个承诺。而且你不必,在Angular中已经有$ q的测试,所以你为此编写测试没有意义吗?

  

用$ q.all

将它们包装成一个

这创造了第三个承诺。当承诺A和B都得到解决时,第三个承诺得到解决。

  

测试承诺是否同时得到解决

JavaScript是单线程的,无法同时解析。第三个承诺,即$ q.all()创建的承诺,将在解决第一个和第二个承诺时解决。时间可能在A和B之间通过。

假设A已解决,一小时后B解决了。然后C($ q.all)将在下一个摘要周期中解析(通过$ scope.apply())。

答案 1 :(得分:0)

这是OP在答案中的答案:

it("Should simulate promise",inject(function($q, $rootScope){
            var deferred = $q.defer();
            var promise = deferred.promise;
            var resolvedValue;
            promise.then(function(value){
                resolvedValue  = value;
            });
            //made no promises yet
            expect(resolvedValue).toBeUndefined();
            var application = {
                id: '123',
                name: 'suebalu',
                database: '234',
                folder: 'c:',
                version: '1.2',
                file: 'previewPubFile',
                date: '2009-01-01'
            };

            deferred.resolve({
                id: '123',
                name: 'suebalu',
                database: '234',
                folder: 'c:',
                version: '1.2',
                file: 'previewPubFile',
                date: '2009-01-01'
            });
            $rootScope.$apply();
            expect(resolvedValue).toEqual(application);
        }));