简体   繁体   中英

Unit testing AngularJS lazy-loaded controller

I am using this strategy to lazy-load stuff with RequireJS in my AngularJS app:

define([
  'src/services/dependency_resolver', // resolves promise when dependencies are `require`d
  'json!modules.json'
], function (dependencyResolver, modules) {
  var app = angular.module('myApp', [ 'ngRoute' ]);

  app.config(function ($controllerProvider, $routeProvider) {
    app.lazy = {
      controller: $controllerProvider.register
      // <...> other providers
    };

    angular.forEach(modules, function (moduleConfig) {
      angular.forEach(moduleConfig.routes, function (route) {
        $routeProvider.when(route.path, {
          templateUrl: route.templateUrl,
          controller: route.controller,
          resolve: dependencyResolver(moduleConfig.dependencies)
        });
      });
    });
  });

  return app;
});

But I'm not sure what is the correct way test a lazy-loaded controller. It is registered like this:

define(['src/app'], function (app) {
  app.lazy.controller('MainCtrl', function () {
    //
  });
});

And this is my current spec:

describe('`MainCtrl` controller', function () {

  var Ctrl,
      $scope;

  beforeEach(angular.mock.module('myApp'));

  beforeEach(function (done) {
    require(['module/main'], done);
  });

  beforeEach(function () {
    angular.mock.inject(function ($rootScope, $controller) {
      $scope = $rootScope.$new();

      Ctrl = $controller('MainCtrl', {
        $scope: $scope
      });
    });
  });

  it('should ...', function () {
    console.log(Ctrl);
  });

});

With this spec, an error occurs when controller is being registered, because app.lazy is undefined.

So the question is how to test such controllers?

Cheers!

I was experiencing a similar problem when writing my unit test using the "lazy" property to register my controller. The problem with this approach is that when in the context of a unit test, the module config block will not be executed and as a result, app.lazy will resolve to undefined .

To solve your problem, instead of using provider registration methods to set your properties of app.lazy , the provider registration method should be used to override their counterparts on the module. In other words, your config block should now become:

`app.config(function ($controllerProvider, $routeProvider) {  
    app.controller = $controllerProvider.register
    // <...> other providers  
    .......
}`

Instead of register your controller using (app.lazy):

`define(['src/app'], function (app) {
   app.lazy.controller('MainCtrl', function () {
   //
   });
});`

you can just define like this:

`define(['src/app'], function (app) {
   app.controller('MainCtrl', function () {
   //
   });
});`

And this should work! Hopefully this can help, and please let me know if this works out or not.

First of all, thank you for the reference you provided - the article is really interesting.

Author of the article is using AngularJs providers to implement his strategy. The thing is, that AngularJs doesn't have providers for 'specs'. So my opinion is that you should omit this strategy in your unit tests.

On this basis, I think, that you should add AMD to your spec file. Define your controller as a dependency in your spec. After this, you may just require all your specs somewhere in main-spec.js and launch your testing framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM