如何在我的应用程序中测试我的http请求

时间:2015-02-05 23:36:14

标签: javascript angularjs unit-testing karma-jasmine

我正在尝试为我的应用编写单元测试,我有以下问题

在我的控制器中,我有类似

的东西
 $scope.test1 = function() {
     productFactory.getName()
         .then(function(products){
             $scope.result = products;
          })
} 

productFactory

angular.module('myApp').factory('productFactory', function($http) {
    var factoryObj = {};
    factoryObj.getName = function() {
        return http.get(url)
    }

    return factoryObj
})

在我的单元测试文件中

describe('test here', function () {
    var testCtrl, scope, httpBackend, mockFactory;

    beforeEach(module('myApp', function($provide){
        $provide.value('productFactory', mockFactory);
    }));

    // Initialize the controller and a mock scope
    beforeEach(inject(function (_$controller_, _$rootScope_, _$httpBackend_,  _productFactory_) {
        scope = _$rootScope_.$new();
        httpBackend = _$httpBackend_;
        mockFactory = _productFactory_;

        testCtrl = _$controller_('testCtrl', {
            $scope: scope
        });

    it('should get product name', function() {       
        scope.test1();
        //I am not sure how to test the results
    });
}));

当我进行业力测试时,它给了我

TypeError: 'undefined' is not an object (evaluating 'productFactory.getName()')

我不确定如何测试http结果并修复错误。任何人都可以帮我吗?非常感谢!

1 个答案:

答案 0 :(得分:1)

首先,您不必担心使用$provide

beforeEach(module('myApp'));

<强> 1。没有$httpBackend(完全模拟服务)

然后,productFactory将传递到您的控制器,但您希望spyOn getName()

// Initialize the controller and a mock scope
beforeEach(inject(function (_$controller_, _$rootScope_, _$httpBackend_,  _productFactory_) {
    scope = _$rootScope_.$new();
    httpBackend = _$httpBackend_;
    mockFactory = _productFactory_;

    // add spy for the method, wrap with $q.when so it returns a promise
    spyOn(mockFactory, 'getName').and.returnValue($q.when('Pizza!'));

    testCtrl = _$controller_('testCtrl', {
        $scope: scope,
        productFactory: mockFactory  // pass in here
    });

然后,您必须进行$digest周期,以便承诺将通过:

it('should get product name', function() {       
    scope.test1();

    // hit the $digest        
    scope.$apply();

    // expectation
    expect(scope.result).toBe('Pizza!')
});

<强> 2。使用$httpBackend

// Initialize the controller and a mock scope
    beforeEach(inject(function (_$controller_, _$rootScope_, _$httpBackend_) {
        scope = _$rootScope_.$new();
        httpBackend = _$httpBackend_;

        // set up httpBackent
        httpBackend.when('GET', '/products')
                            .respond([{ name: 'Pizza!'}, {name: 'Sandwich'}]);

        testCtrl = _$controller_('testCtrl', {
            $scope: scope
        });

在这种情况下,我们根本不需要嘲笑工厂。然后,当我们希望http调用返回时,我们只需要flush $httpBackend

it('should get product name', function() {       
    scope.test1();

    // hit the $digest with flush        
    httpBackend.flush();

    // expectation
    expect(scope.result.length).toBe(2)
});