簡體   English   中英

unit testing angularjs $ q.all - promise永遠不會完成

[英]unit testing angularjs $q.all - promise never completes

我正在嘗試測試我構建的服務,該服務使用Angular的$ q Promise實現。 我正在使用Karma,Mocha,Chai,Sinon,Sinon Chai和Chai的組合作為承諾。

我寫的所有測試和返回的承諾都是通過但拒絕或使用$q.all([ ... ]) 我已經嘗試了所有我能想到的但是我似乎無法找到問題所在。

以下是我正在測試的超薄版本:

"use strict";


describe("Promise", function () {

    var $rootScope,
        $scope,
        $q;

    beforeEach(angular.mock.inject(function (_$rootScope_, _$q_) {
        $rootScope = _$rootScope_;
        $q = _$q_;
        $scope = $rootScope.$new();
    }));

    afterEach(function () {
        $scope.$apply();
    });

    it("should resolve promise and eventually return", function () {

        var defer = $q.defer();

        defer.resolve("incredible, this doesn't work at all");

        return defer.promise.should.eventually.deep.equal("incredible, this doesn't work at all");
    });

    it("should resolve promises as expected", function () {

        var fst = $q.defer(),
            snd = $q.defer();

        fst
            .promise
            .then(function (value) {
                value.should.eql("phew, this works");
            });

        snd
            .promise
            .then(function (value) {
                value.should.eql("wow, this works as well");
            });

        fst.resolve("phew, this works");
        snd.resolve("wow, this works as well");

        var all = $q.all([
            fst.promise,
            snd.promise
        ]);

        return all.should.be.fullfiled;
    });

    it("should reject promise and eventually return", function () {
        return $q.reject("no way, this doesn't work either?").should.eventually.deep.equal("no way, this doesn't work either?");
    });

    it("should reject promises as expected", function () {

        var promise = $q.reject("sadly I failed for some stupid reason");

        promise
            ["catch"](function (reason) {
                reason.should.eql("sadly I failed for some stupid reason");
            });

        var all = $q.all([
            promise
        ]);

        return all.should.be.rejected;
    });

});

第三次,最后一次和第一次測試是失敗的。 實際上它沒有失敗,它只是在超過超時后才解決,我得到一個Error: timeout of 2000ms exceeded

編輯 :我剛剛嘗試用Kris Kowal對承諾的實施進行測試,它的工作原理很好。

PS 我實際上發現在Mocha,Chai或Chai As Promised的碗里有一些時間,並且afterEach鈎子在超時之后被調用。

afterEach()用於清理,而不是在准備之后但在測試之前執行代碼。 $scope.$apply()也不是清理。

您需要執行以下操作:

// setup async behavior
var all = $q.all(x.promise, y.promise)

// resolve your deferreds/promises
x.reject(); y.reject();

// call $scope.$apply() to 'digest' all the promises
$scope.$apply();

// test the results
return all.should.be.rejected;

您在測試完成后進行$apply() ,而不是在設置和評估之間。

我試圖找出為什么測試沒有通過,即使乍一看他們應該。 當然我必須移動$scope.$apply(); 來自afterEach因為那不是@proloser提到的地方。

即使我已經這樣做了,測試仍然沒有通過。 我還打開了關於chai-as-promiseangular的問題 ,看看我是否得到任何輸入/反饋,我實際上被告知它最有可能不起作用。 原因可能是因為Angular $q依賴於摘要階段,這在chai-as-promsied庫中沒有考慮到。

因此,我用Q而不是$ q檢查了測試,它運行得很好,從而加強了我的假設,即錯誤不在chai-as-promise庫中。

我最終放棄了chai-as-promise,我用Mocha的done回調改寫了我的測試(即使在幕后,chai-as-promise也是如此):

"use strict";


describe("Promise", function () {

    var $rootScope,
        $scope,
        $q;

    beforeEach(angular.mock.inject(function (_$rootScope_, _$q_) {
        $rootScope = _$rootScope_;
        $q = _$q_;
        $scope = $rootScope.$new();
    }));

    it("should resolve promise and eventually return", function (done) {

        var defer = $q.defer();

        defer
            .promise
            .then(function (value) {
                value.should.eql("incredible, this doesn't work at all");
                done();
            });

        defer.resolve("incredible, this doesn't work at all");

        $scope.$apply();

    });

    it("should resolve promises as expected", function (done) {

        var fst = $q.defer(),
            snd = $q.defer();

        fst
            .promise
            .then(function (value) {
                value.should.eql("phew, this works");
            });

        snd
            .promise
            .then(function (value) {
                value.should.eql("wow, this works as well");
            });

        fst.resolve("phew, this works");
        snd.resolve("wow, this works as well");

        var all = $q.all([
            fst.promise,
            snd.promise
        ]);

        all
            .then(function () {
                done();
            });

        $scope.$apply();

    });

    it("should reject promise and eventually return", function (done) {

        $q
            .reject("no way, this doesn't work either?")
            .catch(function (value) {
                value.should.eql("no way, this doesn't work either?");
                done();
            });

        $scope.$apply();

    });

    it("should reject promises as expected", function (done) {

        var promise = $q.reject("sadly I failed for some stupid reason");

        promise
            ["catch"](function (reason) {
                reason.should.eql("sadly I failed for some stupid reason");
            });

        var all = $q.all([
            promise
        ]);

        all
            .catch(function () {
                done();
            });

        $scope.$apply();

    });

});

以上測試將按預期通過。 可能還有其他方法可以做到這一點,但我無法弄清楚其他方面,所以如果其他人這樣做,那么將其發布以便其他人可以從中受益將會很棒。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM