3

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.

1
  • What errors are you seeing? Does your source.min.js run correctly on your site? Commented Mar 30, 2016 at 11:11

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.