如何在组件上测试 Angularjs 路由的解析值? [英] How to test Angularjs route's resolve value on component?

查看:31
本文介绍了如何在组件上测试 Angularjs 路由的解析值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 angular@1.5.8 并在路由级别为我的一个组件解析一些资源.该组件按预期工作,但我的测试现在失败了.

I'm using angular@1.5.8 and resolve some resource at the route level for one of my component. The component works as expected but my test fails now.

PhantomJS 2.1.1 (Linux 0.0.0) module ag.expense-claim ExpenseClaimController: should load data FAILED
        TypeError: undefined is not an object (evaluating 'vm.attachedReceipts.results') (line 16)
        ExpenseClaimViewController@app/expenses/expense_claim.js:16:50
        ExpenseClaimViewController@[native code]
        instantiate@node_modules/angular/angular.js:4733:61
        $controller@node_modules/angular/angular.js:10369:39
        node_modules/angular-mocks/angular-mocks.js:2221:21
        $componentController@node_modules/angular-mocks/angular-mocks.js:2264:25
        test/expenseSpec.js:18:40
        invoke@node_modules/angular/angular.js:4718:24
        workFn@node_modules/angular-mocks/angular-mocks.js:3085:26
        loaded@http://localhost:9876/context.js:151:17
        inject@node_modules/angular-mocks/angular-mocks.js:3051:28
        test/expenseSpec.js:14:26
        test/expenseSpec.js:11:13
        global code@test/expenseSpec.js:1:9
        Error: No pending request to flush ! in node_modules/angular-mocks/angular-mocks.js (line 1799)
        flush@node_modules/angular-mocks/angular-mocks.js:1799:76
        test/expenseSpec.js:53:31
        loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0): Executed 43 of 43 (1 FAILED) (0.257 secs / 0.387 secs)
error Command failed with exit code 1.

测试

describe('ExpenseClaimController:', function () {
    var $scope, ctrl, attachedReceipts;

    beforeEach(inject(function ($rootScope, $componentController, $stateParams) {
        var attachedReceipts = {results: [{}]};
        $scope = $rootScope.$new();
        $stateParams.expenseClaimId = 1;
        ctrl = $componentController('expenseClaim', {
            $scope: $scope,
            attachedReceipts: attachedReceipts
        });
    }));

    it('should load data', function () {
       …
    });

组件

angular.module('ag.expenses')
    .component('expenseClaim', {
        templateUrl: '…',
        controller: ExpenseClaimViewController,
        controllerAs: 'vm',
        bindings: {
            attachedReceipts: "<"
        }
    });

function ExpenseClaimViewController($stateParams, $uibModal, API, gettextCatalog, alert) {
    var vm = this;
    vm.attachedReceipts = vm.attachedReceipts.results;
    …
}

路线

 .state('expense-claim', {
        url: '/home_expense_report/:expenseClaimId',
        template: '<expense-claim attached-receipts="$resolve.attachedReceipts"></expense-claim>',
        resolve: {
            attachedReceipts: function (API, $stateParams) {
                return API.TransportCostAttachment.query({expenseClaimId: $stateParams.expenseClaimId}).$promise;
            }
        }
    })

问题

我基于 在测试状态配置时如何模拟 ui-router 的解析值?无法让它工作.我错过了什么?

Question

I implement my solution based on How can I mock ui-router's resolve values when testing a state's configuration? but still can't get it to works. What am I missing?

推荐答案

除了 Ameer 的回复,我还想提供更多细节,因为我费了好大劲才找到它们,如果您有一个组件并且需要要直接对控制器进行单元测试,或者如果您想测试模板,您有两种方法可以创建具有绑定的控制器(它们是否来自 ui-router 的解析并不重要)

In addition to Ameer response, I'd like to provide a few more details as I struggled a lot to find them, if you have a component and you need to unit test the controller directly or if you want to test the template, you have two ways of creating the controller that have bindings (whether they are coming from a resolve from ui-router or not doesn't matter)

- 对组件控制器进行单元测试:

就像 Ameer 所说,您应该将其作为绑定传递:

Like Ameer said, you should pass it as a binding:

beforeEach(inject(function(_$componentController_) {
  $componentController = _$componentController_;
}));

it('should expose a `hero` object', function() {
  // Here we are passing actual bindings to the component
  var bindings = {hero: {name: 'Wolverine'}};
  var ctrl = $componentController('heroDetail', null, bindings);

  expect(ctrl.hero).toBeDefined();
  expect(ctrl.hero.name).toBe('Wolverine');
});

$onInit 方法:

如果你的控制器有 $onInit() 方法,它不会像你期望的那样自动执行,你需要在创建控制器后手动调用该方法,更多细节在这个 问题在这里

If your controller has $onInit() method, it won't be executed automatically like you expect, you need to manually call the method after creating the controller, more details on this issue here

- 对组件模板进行单元测试:

在对组件模板进行单元测试时,您仍然需要实例化控制器,您可以这样做:

When unit testing the template of a component, you still need to instantiate the controller, this is how you can do:

beforeEach(inject(($injector) => {
  $rootScope = $injector.get('$rootScope');
  $compile = $injector.get('$compile');
  scope = $rootScope.$new();
  scope.attachedReceipts = {results: [{}]};;

  template = $compile('<expense-claim attached-receipts="attachedReceipts"></expense-claim>')(scope);
  scope.$apply();
});

it('should test something', () => {
  //Example of something you could test
  expect(template.find('h3').html()).to.eq('this is our first content page');
});

使用第二种方法,将调用 $onInit() 方法,因此您无需手动调用它.关于如何在组件中对模板进行单元测试的完整教程 可以在这里找到

With this second method, the $onInit() method will be called, so you don't need to call it manually. A full tutorial on how to unit test a template within a component can be found here

这篇关于如何在组件上测试 Angularjs 路由的解析值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆