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

How to test my http request in my app

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

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

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

产品工厂

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 结果并修复错误。谁能帮我解决这个问题?非常感谢!

首先,你不用担心使用$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 循环,这样 promise 才会调用:

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 调用 return:

时,我们只需要 flush $httpBackend
it('should get product name', function() {       
    scope.test1();

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

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