簡體   English   中英

在測試AngularJS控制器時,如何在$ http.get承諾中模擬結果?

[英]How do I mock the result in a $http.get promise when testing my AngularJS controller?

經過多次閱讀后,似乎從AngularJS控制器調用Web服務的推薦方法是使用工廠並從中返回一個promise。

這里我有一個簡單的工廠,它調用一個示例API。

myApp.factory('MyFactory', ['$http',function($http) {
var people = {
        requestPeople: function(x) {
            var url = 'js/test.json';
            return $http.get(url);
        }
    };
return people;
}]);

這就是我在控制器中調用它的方式

myApp.controller('MyCtrl1', ['$scope', 'MyFactory', function ($scope, MyFactory) {
        MyFactory.requestPeople(22).then(function(result) {
             $scope.peopleList = result;
        });
}]);

雖然它工作得很好,我希望能夠嘲笑result是在傳遞時, then被調用。 這可能嗎?

到目前為止,我的嘗試沒有產生任 這是我的嘗試:

//Fake service
var mockService = {
    requestPeople: function () {
        return {
            then: function () {
                return {"one":"three"};
            }
        }

    }
};


//Some setup
beforeEach(module('myApp.controllers'));
var ctrl, scope;

beforeEach(inject(function ($rootScope, $controller) {
    scope = $rootScope.$new();

    ctrl = $controller('MyCtrl1', { $scope: scope, MyFactory: mockService });
}));

//Test
it('Event Types Empty should default to false', inject(function () {
    expect(scope.peopleList.one).toBe('three');
}));

我在karma運行器中運行時得到的錯誤是

TypeError:'undefined'不是對象(評估'scope.peopleList.one')

如何使用我的模擬數據進行此測試?

我不認為$ httpBackend就是你在這里所追求的,你想要整個工廠被嘲笑而不依賴於$ http?

看一下$ q ,特別是Testing頭下的代碼示例。 您的問題可能會使用如下代碼解決:

'use strict';

describe('mocking the factory response', function () {

    beforeEach(module('myApp.controllers'));

    var scope, fakeFactory, controller, q, deferred;

    //Prepare the fake factory
    beforeEach(function () {
        fakeFactory = {
            requestPeople: function () {
                deferred = q.defer();
                // Place the fake return object here
                deferred.resolve({ "one": "three" });
                return deferred.promise;
            }
        };
        spyOn(fakeFactory, 'requestPeople').andCallThrough();
    });

    //Inject fake factory into controller
    beforeEach(inject(function ($rootScope, $controller, $q) {
        scope = $rootScope.$new();
        q = $q;
        controller = $controller('MyCtrl1', { $scope: scope, MyFactory: fakeFactory });
    }));

    it('The peopleList object is not defined yet', function () {
        // Before $apply is called the promise hasn't resolved
        expect(scope.peopleList).not.toBeDefined();
    });

    it('Applying the scope causes it to be defined', function () {
        // This propagates the changes to the models
        // This happens itself when you're on a web page, but not in a unit test framework
        scope.$apply();
        expect(scope.peopleList).toBeDefined();
    });

    it('Ensure that the method was invoked', function () {
        scope.$apply();
        expect(fakeFactory.requestPeople).toHaveBeenCalled();
    });

    it('Check the value returned', function () {
        scope.$apply();
        expect(scope.peopleList).toBe({ "one": "three" });
    });
});

我已經添加了一些關於$ apply的測試,直到我開始玩這個我都不知道!

高格

暫無
暫無

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

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