【问题标题】:Angular ui-route testing using mocha chai and sinon使用 mocha chai 和 sinon 进行 Angular ui-route 测试
【发布时间】:2015-10-01 22:33:52
【问题描述】:

我需要使用 mocha chai 和 sinon 在 angularjs 中测试以下代码

$scope.send = function() {
    $state.transitionTo('module.sendhome');
}; 

以下是相同的测试用例

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

在运行上述测试用例时出现如下错误。 错误:没有这样的状态'module.sendhome'

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

【问题讨论】:

  • 顺便说一句,请使用$state.go$state.go 在后台调用 $state.transitionTo,但设置了一些常用设置。 Relevant docs

标签: angularjs unit-testing mocha.js sinon chai


【解决方案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

如果您想确保在调用 $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();
});

【讨论】:

  • 不过,请参阅this article 了解您不拥有的模拟/存根类型。
  • 公平点。我将添加一个关于如何在 $state 实现保持不变的情况下通过的答案。
  • @DanPantry 我添加了另一部分,介绍如何保持第三方实现完整,设置对其使用的期望并确保它不会使构建崩溃。你怎么看?
  • 我认为这篇文章的重点不是避免覆盖方法本身,而是实际上避免测试(在此级别)您实际与该协作者交互。因此,您无需进行单元测试,即使用 Y 参数调用 X 方法,而是进行集成测试,以验证在方法之前您处于状态 A 和之后您处于状态 B。
  • 是的,但这不是单元测试——现在我们正在进入集成测试领域,这比单元测试要慢得多,而且层次更高。但公平地说,OP 从未提及他是想编写完整的集成测试还是单元测试。
猜你喜欢
  • 2016-05-26
  • 2023-03-22
  • 2015-12-01
  • 2021-09-27
  • 2019-02-14
  • 2018-04-08
  • 1970-01-01
  • 2013-04-11
  • 2017-02-18
相关资源
最近更新 更多