Testing a controller in Angular with several dependencies - angularjs

I am learning to write unit tests for my angular app. My controller has several dependencies upon Resources, factories, services etc
angular.module('app').controller('Ctrl1',['$scope','Factory1','Factory2','Resource1','Resource2' ... and so on
The Resource1, Resource2, etc of course fetch data from the server. Several of these resources are used to fetch data from the server and initialize $scope.
After reading innumerous tutorials all over the net, I have a few queries on the right way to write my jasmine tests
In the beforeEach section of the jasmine test, am I suppose to provide all dependencies right away or should I provide only the ones I care about testing
What I want to test is that Resource1 gets called and fetches some data and intializes some part of $scope then Resource2 gets called and fetches some data and initializes some other part of scope etc
What is the right way to perform the above. I mean am I actually suppose to fetch the data in the test or should I be using some mock http service. I know tutorials mention that we should use mock http service but then how will this test my controller since I am not actually fetching the right data.
This part is really confusing and I have yet to find a blog/article that explains this clearly (I might just write one once I figure things out.. I am sure others are confused too)

Where to Provide Dependencies
You should provide all of your dependencies in your first beforeEach statement. I mock/fake mine with SinonJs. This helps you take advantage of angular's dependency injection to isolate each piece of your application. You should never call a dependency and expect an actual instance of it to return data in a unit test, as that would increase the coupling of your code and make it far more brittle.
Mocking Resource Calls
For resource calls, I simply create a fake resource object with promises and whatnot included. You can then resolve or reject those promises and provide fake data to test your controller logic.
In the plunk below, I've essentially mocked out a whole promise chain. You simply tell your tests to either reject or resolve those promises, faking a successful or failure call to the resource. You then have to make sure your scope cycles with scope.$apply(). I actually forgot to do this which caused me quite a bit of trouble just now.
Conclusion
Here is the Plunk. Let me know if you need to see how I test the actual resource code in my repositories. In those services I have to actually mock out the HTTP calls, which Angular makes extremely easy.
I'm not sure any of this is "Best Practice" but it has worked for me. I learned the basics from looking at other people's source code and watching this Pluralsite video AngularJS Fundamentals which has a very small section on testing.
Useful Resources
Testing AngularJS Directives. This is the hardest thing to test and understand in Angular. Or at least it was for me.
This one is on Dependency Injection in Angular. I have it marked
about where they start talking about unit testing.
This Plural Sight Course got me started with testing JavaScript in general. Very helpful for learning Jasmine if you are new to it.
AngularJS Github repo is very useful if you want to see Jasmine tests in action. Here is a set of tests that simulates a HTTP Backend.

Related

How confined should my unit tests be (Angular perspective)?

I am currently writing unit tests for an Angular Controller that calls functions on a Service. I use jasmine spies to make sure that the call to the service passes in the correct parameters. Everything seems okay; this is more or less just testing the configuration of the Controller. I also test the returned value: the returned object contain certain properties and they are valid. Again, my confidence is high although the unit test has now entered into integration test area. I'm certain there are no bugs in this piece of functionality.
We refactored the service. It's function definition changed as well as the returned object. Tests all over the application are broken. To me, that almost seems okay. I should have lots of failing tests. A central point in my application no longer works. However, I'd also argue that changing an endpoint shouldn't be this big of a hassle.
So my question is: how should I test the call to the service? Am I doing too much by checking both the call and the response? IMO the response is all I should care about (as the parameters are implicitly being tested as well). Still, many tests seem to be failing for a simple change to an abstraction layer.

Good architecture MVC, API-calls

Me and some friends are currently doing a project where we are designing a webpage, where we do a number of api-calls using ajax.
We are using the Angular-framework, and we are wondering what is the correct architecture on where to put the API-calls. Right now we have them in our controllers, and saving the results as $scope-objects.
We are however wondering if it would actually be better praxis to have the API-calls in the model. We have been googling a lot, and can't seem to find an answer.
Encapsulating API calls in services is a good idea, but don't try to hide the fact that you are making web requests in your code. Have the services/model return descriptive promises and have your controller use the promises and handle errors gracefully. If using REST, you might want to use Angular's built in $resource factory. If the code is easy to unit test, it will be a sign that you're doing a good job. Being able to easily mock the services will make your controllers a lot easier to test.

Why do I need to inject the controllers I want in my app?

I am reading the source code for an app which reads as follows:
angular.module('graffio', [
'graffio.signupController',
'graffio.loginController',
'graffio.mainController',
'ui.router'
])
I have quite a few questions! So much confusion...
How is code loading these controllers which are defined later in the
code?
Why do I even need to state which controllers I want in my
app? Why can't I just have all the ones I declare?
Why does the angular documentation use the word 'injectable' so much? Isn't
injectable just the same as require?
With Angular, you can group as much or as little code into a module as you like. And you can compose modules together, like the author of the app you are looking at has done. The final module will have all of the services, config blocks, routes, controllers, directives, filters and so on that are in all of the modules it depends on as well as its own module.
This author has chosen to put each controller into its own module. Which is why the main module needs to depend on each of those modules. In my opinion, this seems like overkill, but it is what has been done, and all you need to do is understand it, not agree with it.
In answer to your other questions:
How is code loading these controllers which are defined later in the code?
When your code first runs, all the modules will be declared, and populated with directives, routes, controllers, services and so on. Nothing gets used yet. So long as when the code you have above is run, the other modules have already been declared then everything is fine (this may be done by a build process such as a Grunt task).
Then, when the document.ready event occurs, Angular looks through your HTML for an ng-app directive that says which module to load as your application. It then does what it calls the "bootstrap" process for that module.
Why do I even need to state which controllers I want in my app? Why can't I just have all the ones I declare?
Because this author has put each controller in their own module. If you put all the controllers you want into one module, then you don't need to declare them like that.
Why does the angular documentation use the word 'injectable' so much? Isn't injectable just the same as require?
Sort of. It is similar in that you are asking for a dependency by name and then using it.
It is different in that with require you can't typically modify what value is retrieved for a given dependency at runtime. With dependency injection, you can swap or modify dependencies at run time if you so choose (before your app starts properly and the dependencies are injected into the code using them).
This is perfect for testing, so that you can use a mock (fake) version of a dependency for testing purposes, instead of using the normal version. Think of a service that makes a call to get some data from the server and returns a promise. You can just create a mock version of that service that doesn't call to the server, just returns some test data immediately. This makes your unit tests fast, and means you don't need to be running your web server for them to work.

Dynamically override angular service?

Use case:
I'm writing system tests using Geb/Selenium (so outside of angular).
I want to decorate $http to log all requests/responses at run time.
and here's the catch: without touching the source code.
Before you rush to answer "use $provide#decorator", for example,
http://blog.xebia.com/2014/08/08/extending-angularjs-services-with-the-decorate-method/
That solution for this use case means adding a test hook into production code... that's normally a bad thing I want to avoid if possible.
Update: Geb allows you to run Javascript in the browser window. So just for the heck of it I ran the tutorial code to decorate $http. Unfortunately, it didn't work because apparently you can't re-config the app after it's been loaded. But even if it did work, this brings up another interesting point---I need to override $http before any modules have had a chance to use it.
Since decorating $http service would be the cleanest way of doing this, you can avoid polluting production code by using something like ng-constants and gulp/grunt to only add decoration code for a 'test' environment.
See related Q/A here: How do I configure different environments in Angular.js?
If you are inclined on changing this at runtime(where runtime takes place in a test environment), you may need to go 'closer to the metal' and deal with XMLHttpRequests: Add a "hook" to all AJAX requests on a page

Purpose of AngularJS Services

I'm new to AngularJS. I'm currently looking at the services. Some of these services look like the replace functions already available in JavaScript. For instance, the $timeout service. Why does AngularJS have these services? Is there a technical reason? Are there any advantages to this approach? I just don't understand the need for using these services.
Thank you for any help.
A service is a function or an object, with a set of methods, that could be used by several components (controllers, directives, filters, other services) of your application.
The main advantage that "wrapping" services like $timeout or $window have over their global functions equivalent is that they're injected by Angular, and can thus be mocked in unit tests, i.e. replaced by fake implementations.
Read the chapter about dependency injection in the angular documentation. Regarding the $timeout service in particular, its documentation explains what it does in addition to the native setTimeout() function.
Angular uses dirty check -- it keeps track of all variables that should be updated automatically and in case of any changes iterates through them as many times as needed (as there can be interdependence between observing variables). (To be precise if there are too many iterations something wrong is probably with your code and exception is raised).
The main reason behind $timeout is to signal to Angular engine that you will be making some changes to the observing variables in the callback. In case you would call normal timeout there is a way to inform Angular about those changes by calling e.g. $scope.$apply(function() {...}).
The other big reason, as #JB Nizet stated is that mocking is much easier.
Service is a way to store persistent information over your application.
unlike the $scope, which is an new child of $rootScope per each route\controller.
The purpose of the Angular-specific implementation of already existent functions, is to make your life and work easier, by automatically telling angular to register your changes, and apply them to the current scope at the next $digest iteration.
I'll be happy to address any other questions.
Good luck with Angular! :)
I will now create an example plunk to emphasize the idea to you
UPDATE:
This is the plunker:
http://plnkr.co/edit/mVmhZpEdsZDQ0MUQpFJ7?p=preview
I used ng-change and the native change
keyup event to explain the point.
while using the angular built in ng-change directive requires no additional effort nor code, using the native events requires wrapping everything in the scope.$apply function/
calling scope.$digest manually.
(run the code and see for yourself)
Check out this older answer which covers Services, Providers and Factories.
AngularJS: Service vs provider vs factory

Resources