用于解析的存根工厂 [英] Stubbing factory being used in resolve

查看:15
本文介绍了用于解析的存根工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在控制器中对我的状态进行单元测试.我想要做的是将我的 items 工厂存根,因为我有单独的单元测试来涵盖该功能.我很难让 $injector 实际注入工厂,但似乎我让 $provider 知道我想使用我的假实例化控制器时的 items 对象.作为免责声明,我是 Angular 的新手,如果我的代码看起来很糟糕,我会喜欢一些建议.

I'm trying to unit test my states in an controller. What I want to do is stub out my items factory, since I have separate unit tests that cover that functionality. I'm having a hard time getting the $injector to actually inject the factory, but it seems like I'm letting the $provider know that I want to use my fake items object when it instantiates the controller. As a disclaimer I'm brand new to angular and would love some advice if my code looks bad.

目前,当我运行测试时,我收到消息:

Currently when I run the test I get the message:

Error: Unexpected request: GET /home.html
    No more request expected
        at $httpBackend (node_modules/angular-mocks/angular-mocks.js:1418:9)
        at n (node_modules/angular/angular.min.js:99:53)
        at node_modules/angular/angular.min.js:96:262
        at node_modules/angular/angular.min.js:131:20
        at m.$eval (node_modules/angular/angular.min.js:145:347)
        at m.$digest (node_modules/angular/angular.min.js:142:420)
        at Object.<anonymous> (spec/states/homeSpec.js:29:16)

我的模拟项目工厂似乎没有被注入到测试中.当我在要存根的方法中放置 console.log 行时,我看到该行正在被调用.

It appears that my mocked items factory isn't being injected into the test. When I place a console.log line in the method I want to stub in the items factory I see that line being invoked.

我要测试的代码如下:

angular.module('todo', ['ui.router'])
// this is the factory i want to stub out...
.factory('items', ['$http', function($http){
  var itemsFactory = {};
  itemsFactory.getAll = function() {
    // ...specifically this method
  };
  return itemsFactory;
}])
.controller('TodoCtrl', ['$scope', 'items', function($scope, items) {
  // Do things
}])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider){
  $stateProvider
    .state('home', {
      url: '/home',
      templateUrl: '/home.html',
      controller: 'TodoCtrl',
      resolve: {
        items: ['items', function(items){
          // this is the invocation that i want to use my stubbed method
          return items.getAll();
        }]
      }
    });

  $urlRouterProvider.otherwise('home');
}]);

我的测试如下所示:

describe('home state', function() {

  var $rootScope, $state, $injector, state = 'home';
  var getAllStub = sinon.stub();
  var items = {
    getAll: getAllStub
  };

  beforeEach(function() {
    module('todo', function($provide) {
      $provide.value('items', items);
    });

    inject(function(_$rootScope_, _$state_, _$injector_) {
      $rootScope = _$rootScope_;
      $state = _$state_;
      $injector = _$injector_;
    });
  });

  it('should resolve items', function() {
    getAllStub.returns('getAll');

    $state.go(state);
    $rootScope.$digest();
    expect($state.current.name).toBe(state);

    expect($injector.invoke($state.current.resolve.items)).toBe('findAll');
  });
});

提前感谢您的帮助!

推荐答案

在单元测试中允许真正的路由器是一个坏主意,因为它打破了隔离并增加了更多的移动部件.我个人认为 $stateProvider 等 stub 是一种更好的测试策略.

Allowing real router in unit tests is a bad idea because it breaks the isolation and adds more moving parts. I personally consider $stateProvider, etc. stubs a better testing strategy.

配置块中的顺序很重要,服务提供者应该在被注入其他模块之前被模拟.如果原始模块具有覆盖模拟服务提供者的 config 块,则应该对模块进行存根:

The order matters in config blocks, service providers should be mocked before they will be injected in other modules. If the original modules have config blocks that override mocked service providers, the modules should be stubbed:

  beforeAll(function () {
    angular.module('ui.router', []);
  });

  beforeEach(function () {
    var $stateProviderMock = {
      state: sinon.stub().returnsThis()
    };

    module(function($provide) {
      $provide.constant('$stateProvider', $stateProviderMock);
    });
    module('todo');
  });

您只需要确保使用预期的配置对象和参数调用 $stateProvider.state:

You just need to make sure that $stateProvider.state is called with expected configuration objects an arguments:

  it('should define home state', function () {
    expect($stateProviderMock.state.callCount).to.equal(1);

    let [homeStateName, homeStateObj] = $stateProviderMock.state.getCall(0).args;

    expect(homeStateName).to.equal('home');
    expect(homeState).to.be.an('object');

    expect(homeState.resolve).to.be.an('object');
    expect(homeState.resolve.items).to.be.an('array');

    let resolvedItems = $injector.invoke(homeState.resolve.items);
    expect(items.getAll).to.have.been.calledOnce;
    expect(resolvedItems).to.equal('getAll');

    ...
  });

这篇关于用于解析的存根工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆