【问题标题】:TypeScript Angular Jasmine + Karma Testing ScopeTypeScript Angular Jasmine + Karma 测试范围
【发布时间】:2015-12-10 04:24:18
【问题描述】:

我花了几个小时试图弄清楚这一点。我编写了简单的 Angular 应用程序,现在我正尝试在 Type Script 中对其进行测试。

控制器:

 export class ProductsController {     
    static $inject = ["ProductService", "$scope"];
    constructor(public productsServices: AngularTest.Interfaces.IProductsService, $scope: any) {


            productsServices.getAllProducts().then((response: ng.IHttpPromiseCallbackArg<AngularTest.Interfaces.IProducts[]>): any => {
            $scope.currentPage = 1;
            $scope.allProducts = <AngularTest.Interfaces.IProducts[]> response.data

                    $scope.cartItems = [];
                    $scope.modalAlerts = [];

                    $scope.maxItems = 3;
                    $scope.totalItems = $scope.allProducts.length;

                    $scope.itemsOnPage = $scope.allProducts.slice(0, $scope.maxItems);
        });

        $scope.pageChanged = function () {
            $scope.itemsOnPage = $scope.allProducts.slice(($scope.currentPage - 1) * $scope.maxItems, $scope.currentPage * $scope.maxItems);
        };
    }
}

和测试:

 describe("TestService", () => {

    var mock: ng.IMockStatic;
    var $httpBackend: ng.IHttpBackendService;
    var service: AngularTest.Services.ProductServices;
    var rootScopeFake;
    var controller;
    var $controller: ng.IControllerService;
    var mockServiceProvider;
    var prop: ng.IPromise<AngularTest.Interfaces.IProducts[]>;
    var q :ng.IQService;

    mock = angular.mock;

    beforeEach(mock.module('app.AngularTS'));

    beforeEach(() => mock.inject(function (_$httpBackend_, $injector, $rootScope, _$controller_, $q) {
        $httpBackend = _$httpBackend_;
        rootScopeFake = $rootScope.$new();     
        service = $injector.get('ProductService');   
        $controller = _$controller_;
        q = $q;
    }));

    afterEach(function () {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });


    it("Should Call API", function () {

        spyOn(service, "getAllProducts").and.callFake(() => {
            var deffered;
            deffered = q.defer();
            deffered.resolve(['xxxx', 'xxxx']);
            return deffered.promise;
        });

        controller = new AngularTest.Controllers.ProductsController(service, rootScopeFake);
        expect(service.getAllProducts).toHaveBeenCalled();
        expect(rootScopeFake.allProducts).toBeDefined();

    }); 
});

当我尝试测试我的 ProductsController 时,我收到 TypeError: 'undefined' is not an object (evalating '$scope.allProducts.length') 为什么?

【问题讨论】:

    标签: c# angularjs unit-testing typescript


    【解决方案1】:

    您将 getAllProducts 的结果作为数组返回:

    deffered.resolve(['xxxx', 'xxxx']);
    

    在您的控制器中,您希望将其分配给响应的数据属性:

    $scope.allProducts = <AngularTest.Interfaces.IProducts[]> response.data
    

    因此,要解决此问题,您需要更改测试以解决如下问题:

    deffered.resolve({data: ['xxxx', 'xxxx']});
    

    更新

    在 Angular 中的 Promise 解析是在一个摘要循环中执行的,这是您需要手动触发的:

    controller = new AngularTest.Controllers.ProductsController(service, rootScopeFake);
    rootScopeFake.$digest(); // <-- this is the important part
    expect(service.getAllProducts).toHaveBeenCalled();
    

    【讨论】:

    • 我没有完全按照你说的那样做,但还是有问题。基本上我无法访问角度控制器内的任何范围值 - 构造函数。例如,如果我尝试做 expect(rootScopeFake.currentPage).toEqual(1);我收到错误:预期未定义等于 1。
    • 我添加了一个更新来处理这种情况......在你的范围内调用 $digest
    • 你是男人。我在这上面浪费了一天。非常感谢
    猜你喜欢
    • 2015-12-07
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多