Angular-Karma 控制器测试:UI-路由器持久 $stateParams 依赖
Angular-Karma controller test: UI-Router persistent $stateParams dependency
我正在尝试围绕控制器构建一些测试。我正在使用 $stateParams 注入测试,并两次导航到相同的状态。第一个测试通过了,但是第二个测试失败了,因为它认为creationId还是1。
it('should navigate to customizer with a creation ID', function (done) {
inject(function ($state, $stateParams, $rootScope) {
$state.go('customizer', {creationId: 1});
$rootScope.$digest();
expect($stateParams).to.have.property('creationId','1');
done();
});
});
it('should navigate to customizer without a creation ID', function (done) {
inject(function ($state, $stateParams, $rootScope) {
$state.go('customizer');
$rootScope.$digest();
expect($stateParams).to.not.have.property('creationId','1');
done();
});
});
为什么会这样?我需要在 beforeEach 或 afterEach 上 运行 清除状态吗?
如问题评论中所述,要使测试对控制器进行测试,$state
应该通过某种方式进行模拟,以验证是否发生了状态转换。
这是我们在one of our open source projects中一直使用的:
angular.module('stateMock', []);
angular.module('stateMock').service('stateMock', function($q) {
'use strict';
this.expectedTransitions = [];
this.transitionTo = function(stateName, params) {
if (this.expectedTransitions.length > 0) {
var expectedState = this.expectedTransitions.shift();
if (expectedState.stateName !== stateName) {
throw Error('Expected transition to state: ' + expectedState.stateName + ' but transitioned to ' + stateName);
}
if (!angular.equals(expectedState.params, params)) {
throw Error('Expected params to be ' + JSON.stringify(expectedState.params) + ' but received ' + JSON.stringify(params));
}
} else {
throw Error('No more transitions were expected! Tried to transition to ' + stateName);
}
// console.log('Mock transition to: ' + stateName + ' with params: ' + JSON.stringify(params));
return $q.when();
};
this.go = this.transitionTo;
this.expectTransitionTo = function(stateName, params) {
this.expectedTransitions.push({
stateName: stateName,
params: params
});
};
this.ensureAllTransitionsHappened = function() {
if (this.expectedTransitions.length > 0) {
throw Error('Not all transitions happened!');
}
};
});
并且 these lines 从规范中应该可以让您清楚地了解如何使用它。
describe('state', function() {
it('should transition correctly on invoking previous', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 7
});
$scope.previous();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on invoking next', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 9
});
$scope.next();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on month change', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 1
});
calendar.month = 1;
$scope.$digest();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on year change', function() {
state.expectTransitionTo('month', {
year: 1979,
month: 8
});
calendar.year = 1979;
$scope.$digest();
state.ensureAllTransitionsHappened();
});
});
我正在尝试围绕控制器构建一些测试。我正在使用 $stateParams 注入测试,并两次导航到相同的状态。第一个测试通过了,但是第二个测试失败了,因为它认为creationId还是1。
it('should navigate to customizer with a creation ID', function (done) {
inject(function ($state, $stateParams, $rootScope) {
$state.go('customizer', {creationId: 1});
$rootScope.$digest();
expect($stateParams).to.have.property('creationId','1');
done();
});
});
it('should navigate to customizer without a creation ID', function (done) {
inject(function ($state, $stateParams, $rootScope) {
$state.go('customizer');
$rootScope.$digest();
expect($stateParams).to.not.have.property('creationId','1');
done();
});
});
为什么会这样?我需要在 beforeEach 或 afterEach 上 运行 清除状态吗?
如问题评论中所述,要使测试对控制器进行测试,$state
应该通过某种方式进行模拟,以验证是否发生了状态转换。
这是我们在one of our open source projects中一直使用的:
angular.module('stateMock', []);
angular.module('stateMock').service('stateMock', function($q) {
'use strict';
this.expectedTransitions = [];
this.transitionTo = function(stateName, params) {
if (this.expectedTransitions.length > 0) {
var expectedState = this.expectedTransitions.shift();
if (expectedState.stateName !== stateName) {
throw Error('Expected transition to state: ' + expectedState.stateName + ' but transitioned to ' + stateName);
}
if (!angular.equals(expectedState.params, params)) {
throw Error('Expected params to be ' + JSON.stringify(expectedState.params) + ' but received ' + JSON.stringify(params));
}
} else {
throw Error('No more transitions were expected! Tried to transition to ' + stateName);
}
// console.log('Mock transition to: ' + stateName + ' with params: ' + JSON.stringify(params));
return $q.when();
};
this.go = this.transitionTo;
this.expectTransitionTo = function(stateName, params) {
this.expectedTransitions.push({
stateName: stateName,
params: params
});
};
this.ensureAllTransitionsHappened = function() {
if (this.expectedTransitions.length > 0) {
throw Error('Not all transitions happened!');
}
};
});
并且 these lines 从规范中应该可以让您清楚地了解如何使用它。
describe('state', function() {
it('should transition correctly on invoking previous', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 7
});
$scope.previous();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on invoking next', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 9
});
$scope.next();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on month change', function() {
state.expectTransitionTo('month', {
year: 2015,
month: 1
});
calendar.month = 1;
$scope.$digest();
state.ensureAllTransitionsHappened();
});
it('should transition correctly on year change', function() {
state.expectTransitionTo('month', {
year: 1979,
month: 8
});
calendar.year = 1979;
$scope.$digest();
state.ensureAllTransitionsHappened();
});
});