如何通过在 ES6 class 中为 angular 控制器模拟单元测试自定义 $filter
how to unit test custom $filter by mocking in ES6 class for angular controller
我有一个为 angular 控制器编写的 ES Class,我正在尝试使用 angular-mock 编写 jasmine 测试。
在构造函数中,我将 $filter 初始化为 this.i18n = $filter('i18n),这基本上是一个本地化过滤器,它采用键、值和 returns 键的本地化值。
我的问题是,由于 class 的构造函数具有 $filter 并且稍后在 class 方法中使用。我的单元测试失败了。我如何使用 $filter 进行测试,这样我的测试才不会失败。我想模拟自定义过滤器
这是我得到的异常
TypeError: this.i18n is not a function
at UsersCtrl.$onInit (test-context.js:35081:41)
at Object.<anonymous> (test-context.js:35031:31)
这里是ES6Class
class UsersCtrl {
constructor($filter) {
this.i18n = $filter('i18n');
this.users = [];
}
//Life cycle Hooks: Initialization
$onInit() {
this.users = [
{name: this.i18n('USERS')}
];
}
}
UsersCtrl.$inject = ['$filter'];
angular.module('app', []).controller('UsersCtrl',UsersCtrl);
export default UsersCtrl;
这是我的单元测试
Import UsersCtrl from './users-controller.js';
describe("given a new User Page", () => {
var UserController;
beforeEach(() => {
angular.mock.module('app');
});
describe("when initialising has completed", () => {
beforeEach(() => {
inject(($rootScope, $controller, $filter) => {
const scope = $rootScope.$new();
const filter = $filter
UserController = $controller("UsersCtrl", { $scope: scope, $filter: filter});
});
});
it("then users array for tab content should be empty initially",() => {
const expectedActive = [];
expect(UserController.users).toEqual(expectedActive);
});
});
});
问题是它运行测试但由于无法使用 this.i18n = $filter('i18n) 进行初始化而失败。我应该如何初始化测试以将 $filter 传递到测试中?我可以模拟过滤器吗,因为我真的不想在这里测试过滤器
您可以:
- 模拟整个
$filter
服务 并在测试中实例化时将其注入控制器;或
- 模拟单个过滤器。 然后您可以在加载模块时使用
$provide.value(key, value)
,其中键是过滤器名称加上后缀:'Filter'(这是 angular 在注册过滤器时在内部做的事情)。
两者的一个例子:
/* Angular App */
(function() {
"use strict";
class UsersCtrl {
constructor($filter) {
this.i18n = $filter('i18n');
this.users = [];
}
$onInit() {
this.users = [{
name: this.i18n('USERS')
}];
}
}
UsersCtrl.$inject = ['$filter'];
angular
.module('app', [])
.controller('UsersCtrl', UsersCtrl);
})();
/* Unit Test */
(function() {
"use strict";
describe('given a new User Page', () => {
let UsersController;
describe('MOCK entire $filter service: when initialising has completed', () => {
beforeEach(() => {
module('app');
inject(($rootScope, $controller) => {
UsersController = $controller("UsersCtrl", {
$scope: $rootScope.$new(),
$filter: () => {
// $filter will be a function that returns a noop function (or whatever we want)
return angular.noop;
}
});
});
});
it('then users array for tab content should be empty initially', () => {
const expectedActive = [];
expect(UsersController.users).toEqual(expectedActive);
});
});
describe('MOCK individual \'i18n\' filter: when initialising has completed', () => {
beforeEach(() => {
module('app', ($provide) => {
// provide a mock (noop function) for our filter.
// Note naming convention, our filter name + 'Filter' suffix.
$provide.value('i18nFilter', angular.noop);
});
inject(($rootScope, $controller, $filter) => {
UsersController = $controller("UsersCtrl", {
$scope: $rootScope.$new(),
$filter: $filter
});
});
});
it('then users array for tab content should be empty initially', () => {
const expectedActive = [];
expect(UsersController.users).toEqual(expectedActive);
});
});
});
})();
<link rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.css" />
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine-html.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/boot.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-mocks.js"></script>
我有一个为 angular 控制器编写的 ES Class,我正在尝试使用 angular-mock 编写 jasmine 测试。
在构造函数中,我将 $filter 初始化为 this.i18n = $filter('i18n),这基本上是一个本地化过滤器,它采用键、值和 returns 键的本地化值。
我的问题是,由于 class 的构造函数具有 $filter 并且稍后在 class 方法中使用。我的单元测试失败了。我如何使用 $filter 进行测试,这样我的测试才不会失败。我想模拟自定义过滤器
这是我得到的异常
TypeError: this.i18n is not a function
at UsersCtrl.$onInit (test-context.js:35081:41)
at Object.<anonymous> (test-context.js:35031:31)
这里是ES6Class
class UsersCtrl {
constructor($filter) {
this.i18n = $filter('i18n');
this.users = [];
}
//Life cycle Hooks: Initialization
$onInit() {
this.users = [
{name: this.i18n('USERS')}
];
}
}
UsersCtrl.$inject = ['$filter'];
angular.module('app', []).controller('UsersCtrl',UsersCtrl);
export default UsersCtrl;
这是我的单元测试
Import UsersCtrl from './users-controller.js';
describe("given a new User Page", () => {
var UserController;
beforeEach(() => {
angular.mock.module('app');
});
describe("when initialising has completed", () => {
beforeEach(() => {
inject(($rootScope, $controller, $filter) => {
const scope = $rootScope.$new();
const filter = $filter
UserController = $controller("UsersCtrl", { $scope: scope, $filter: filter});
});
});
it("then users array for tab content should be empty initially",() => {
const expectedActive = [];
expect(UserController.users).toEqual(expectedActive);
});
});
});
问题是它运行测试但由于无法使用 this.i18n = $filter('i18n) 进行初始化而失败。我应该如何初始化测试以将 $filter 传递到测试中?我可以模拟过滤器吗,因为我真的不想在这里测试过滤器
您可以:
- 模拟整个
$filter
服务 并在测试中实例化时将其注入控制器;或 - 模拟单个过滤器。 然后您可以在加载模块时使用
$provide.value(key, value)
,其中键是过滤器名称加上后缀:'Filter'(这是 angular 在注册过滤器时在内部做的事情)。
两者的一个例子:
/* Angular App */
(function() {
"use strict";
class UsersCtrl {
constructor($filter) {
this.i18n = $filter('i18n');
this.users = [];
}
$onInit() {
this.users = [{
name: this.i18n('USERS')
}];
}
}
UsersCtrl.$inject = ['$filter'];
angular
.module('app', [])
.controller('UsersCtrl', UsersCtrl);
})();
/* Unit Test */
(function() {
"use strict";
describe('given a new User Page', () => {
let UsersController;
describe('MOCK entire $filter service: when initialising has completed', () => {
beforeEach(() => {
module('app');
inject(($rootScope, $controller) => {
UsersController = $controller("UsersCtrl", {
$scope: $rootScope.$new(),
$filter: () => {
// $filter will be a function that returns a noop function (or whatever we want)
return angular.noop;
}
});
});
});
it('then users array for tab content should be empty initially', () => {
const expectedActive = [];
expect(UsersController.users).toEqual(expectedActive);
});
});
describe('MOCK individual \'i18n\' filter: when initialising has completed', () => {
beforeEach(() => {
module('app', ($provide) => {
// provide a mock (noop function) for our filter.
// Note naming convention, our filter name + 'Filter' suffix.
$provide.value('i18nFilter', angular.noop);
});
inject(($rootScope, $controller, $filter) => {
UsersController = $controller("UsersCtrl", {
$scope: $rootScope.$new(),
$filter: $filter
});
});
});
it('then users array for tab content should be empty initially', () => {
const expectedActive = [];
expect(UsersController.users).toEqual(expectedActive);
});
});
});
})();
<link rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.css" />
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine-html.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/2.0.0/boot.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-mocks.js"></script>