简体   繁体   中英

Angular Jasmine tests fail with minified source

I'll try to approach this question with a little bit of abstraction, since going into the code details would be useless.

I have an angular module that is split in 2 source files, say source1.js and source2.js . Then i have 3 unit test files which are designed to test 3 angular service/factory/provider.

The project layout is as follows:

root
|
-dist
   |
   -source.min.js
-src
   |
   -source1.js
   -source2.js
-tests
   |
   -unit
      |
      -service1.js
      -service2.js
      -service3.js

All the tests, run with karma and jasmine, pass and work as expected. See this bit of karma config to get the point:

files: [

  'bower_components/angular/angular.min.js',
  'bower_components/angular-mocks/angular-mocks.js',

  'src/*.js',
  'tests/unit/*.js'
],

Next i minified source1 and source2 with gulpjs into source.min.js and tried to run tests using the minified file, so i changed the karma config as follows:

files: [

  'bower_components/angular/angular.min.js',
  'bower_components/angular-mocks/angular-mocks.js',

  'dist/*.js', // <--- see here.
  'tests/unit/*.js'
],

With this configuration all tests are failing because of angular dependency injection - looks like the provider is not being resolved.

What could cause this? I mean, the source code should be the same.

This is a known problem with angular, dependency injection and minification. Also, the problem resides precisely in the details of the code.

Case 1:

Without explicit injection, angular tries to infer the service from the service name when using declared functions as controllers.

angular.module('app').controller('MyController', MyController);

function MyController(service1, service2, ...){ ... service1.doSomething ...}

Case 2:

With explicit injection, angular uses the controller function parameters in the order in which they were injected.

angular.module('app').controller('MyController', MyController);

MyController.$inject = ['service1', 'service2', ...]

function MyController(a, b, ...){ ... a.doSomething ... }

Case 1 will fail to work every time with minification because the name of the service will change and angular will not be able to infer the service that a, or b or c refer to by just looking at their names.

However, Case 2 will work every time because angular does not have to guess as it is being told by $inject that service1 is a and service 2 is b and so on.

If you are using a build utility like Gulp you can use ng-annotate which will automatically inject the dependencies for you in Case 1 and your code should still work.

In my own opinion and as a matter of style you should use case 2. I tend to follow something close to John Papa's Angular Style Guide

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