您需要删除 $state 和 transitionTo 方法并在上面写下期望。这将使您的单元测试保持干净和灵活,以免触发$state.transitionTo 的实际实现(这反过来又会触发您遇到的错误)。
var $scope, $state;
beforeEach(function () {
$state = {};
module('your_module', function ($provide) {
$provide.value('$state', $state);
});
inject(function ($injector, $controller) {
$state = $injector.get('$state');
$scope = $injector.get('$rootScope').$new();
$controller('your_controller', {
$scope: $scope,
$state: $state
});
});
// Stub API
$state.transitionTo = sinon.stub();
});
it('calls the transitionTo method', function () {
$scope.send();
expect($state.transitionTo).to
.have.been.calledOnce
.and.calledWith('module.sendhome');
});
编辑
根据not stubbing out things we do not own 的概念(我不完全同意,但为了争论,假设我同意)。
不要stub $state.transitionTo,而是spy 就可以了。
现在 - 您必须注册一个与您的期望相匹配的状态,以使 $state.transitionTo 不会崩溃。
var stateProvider;
beforeEach(function () {
module('ui.router', function ($stateProvider) {
stateProvider = $stateProvider;
});
/** The rest of your beforeEach block **/
stateProvider.state('module.sendhome', {});
});
然后在你的it:
it('calls the transitionTo method with the correct params', function () {
var spy = sinon.spy($state, 'transitionTo');
$scope.send();
expect(spy).to
.have.been.calledOnce
.and.calledWith('module.sendhome');
});
编辑#2
如果您想确保在调用 $scope 方法后得到正确的 state,我会查看 this awesomely awesome stateMock。
在您自己之前将stateMock 作为另一个模块注入并编写期望,例如:
afterEach(function () {
$state.ensureAllTransitionsHappened();
});
it('should travel to the correct state', function () {
$state.expectTransitionTo('module.sendhome');
$scope.send();
});