使用摩卡柴和sinon的角度ui路线测试

时间:2015-07-13 15:14:03

标签: angularjs unit-testing mocha sinon chai

我需要使用mocha chai和sinon

在angularjs中测试下面的代码
$scope.send = function() {
    $state.transitionTo('module.sendhome');
}; 

下面是相同的测试用例

it('send' , function () {
    scope.send();
});

运行上面的测试用例获取错误,如下所示。 错误:没有这样的状态' module.sendhome'

在我的测试用例中,需要检查是否使用参数 module.sendhome 调用$ state.transitionTo。

1 个答案:

答案 0 :(得分:1)

您需要隐藏$statetransitionTo方法并写下期望值。这将使您的单元测试保持干净和灵活,从而不会触发$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

如果您想确保在调用state方法后最终找到了正确的$scope,我会调查this awesomely awesome stateMock

在您自己之前注入stateMock作为另一个模块并编写期望,例如:

afterEach(function () {
  $state.ensureAllTransitionsHappened();
});

it('should travel to the correct state', function () {
  $state.expectTransitionTo('module.sendhome');
  $scope.send();
});