我们的Angular项目移至ES6和Reduxjs,现在我正在努力使控制器单元测试正常工作。具体来说,对于类构造函数,我似乎无法正确模拟。根据我的研究,我无法监视ES6类的构造函数,因此我需要模拟其依赖关系,还需要适应ngRedux.connect()促进的词汇“ this”的绑定。

我的测试使其到达构造函数中的connect函数,然后出现错误:“'connect'不是函数”

我认为我在这里可能有几处错误。如果我注释掉构造函数中的连接线,它将进入我的runOnLoad函数,该错误将告诉我fromMyActions不是函数。这是因为redux connect函数将动作绑定到“ this”,因此鉴于这些问题,除非我提供其实现,否则我无法模拟redux。有什么建议吗?我对angular也比较陌生-我最薄弱的领域是单元测试和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);
    });

  });
});

最佳答案

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(我通过角度服务公开了动作创建者),因此存根不处理动作,但应该易于添加。

09-20 17:39