Angular,Redux,ES6,单元测试控制器

时间:2016-02-03 22:03:26

标签: angularjs unit-testing ecmascript-6 redux

我们的Angular项目搬到了ES6和Reduxjs,现在我正努力让控制器单元测试工作。具体来说,当涉及到类构造函数时,我似乎无法正确模拟。从我所研究的内容来看,我无法窥探一个ES6类构造函数,所以我需要模拟它的依赖关系,并且还要适应对词汇的绑定。这个' ngRedux.connect()方便了。

我的测试使它成为构造函数中的connect函数,然后给我错误:"' connect'不是一个功能"

我想我可能有几件事情错了。如果我在构造函数中注释掉连接线,它将进入我的runOnLoad函数,错误将告诉我fromMyActions不是函数。这是因为redux connect函数将动作绑定到“这个”,所以考虑到这些问题,我认为我不能模拟redux,除非我提供它的实现。任何建议?我对角度也相对较新 - 我最薄弱的部分是单元测试和DI。

这是我的模块和控制器:

export const myControllerModule = angular.module('my-controller-module',[]);

export class MyController {

constructor($ngRedux, $scope) {
'ngInject';

  this.ngRedux = $ngRedux;
  const unsubscribe = this.ngRedux.connect(this.mapState.bind(this), myActions)(this);
  $scope.$on('$destroy', unsubscribe);
  this.runOnLoad();
}

mapState(state) {
  return {};
}

runOnLoad() {
   this.fromMyActions(this.prop);
  }
}

myControllerModule 
  .controller(controllerId, MyController
  .directive('myDirective', () => {
    return {
      restrict: 'E',
      controllerAs: 'vm',
      controller: controllerId,
      templateUrl: htmltemplate
      bindToController: true,
      scope: {
        data: '=',
        person: '='
      }
    };
  });

export default myControllerModule.name;

和我的测试:

import {myControllerModule,MyController} from './myController';
import 'angular-mocks/angular-mocks';

describe('test', () => {

  let controller, scope;

  beforeEach(function() {

let reduxFuncs = {
  connect: function(){}
}

angular.mock.module('my-controller-module', function ($provide) {
  $provide.constant('$ngRedux',reduxFuncs);
});

angular.mock.inject(function (_$ngRedux_, _$controller_, _$rootScope_) {
  scope = _$rootScope_.$new();
  redux = _$ngRedux_;

  var scopeData = {
    data : {"test":"stuff"},
    person : {"name":"thatDude"}
  } ;
        scope.$digest();

        controller = _$controller_(MyController, {
        $scope: scope,
        $ngRedux: redux
      }, scopeData);
    });

  });
});

1 个答案:

答案 0 :(得分:3)

Redux背后的想法是,你的大多数控制器都没有或很少有逻辑。逻辑将主要是行动创造者,减少者和选择者。 在您提供的示例中,您的大多数代码只是连接事物。 我个人不测试布线,因为它增加了很少的价值,而且那些类型的测试通常都非常脆弱。

话虽如此,如果你想测试你的控制器,你有两个选择:

  • 使用函数代替控制器的类。对于大多数使用类的控制器没有增加实际价值。而是使用一个函数,并在另一个纯函数中隔离要测试的逻辑。然后,您甚至可以在不需要模拟等的情况下测试此功能。

  • 如果您仍想使用类,则需要使用ng-redux的存根(例如:https://gist.github.com/wbuchwalter/d1448395f0dee9212b70(在TypeScript中))

并像这样使用它:

let myState = {
  someProp: 'someValue'
}

let ngReduxStub;
let myController;
beforeEach(angular.mock.inject($injector => {
  ngReduxStub = new NgReduxStub();

  //how the state should be initially
  ngReduxStub.push(myState);
  myController = new MyController(ngReduxStub, $injector.get('someOtherService');
}));

注意:我个人不使用mapDispatchToProps(我通过角度服务公开我的动作创建者),因此存根不处理动作,但它应该很容易添加。