I've found that mocking $httpBackend in unit tests is usually an indication that the system could benefit from an abstraction.
In the article's scraping example, a service that works like `Scrape.url('success.com')` could be mocked and sidestep the $http boundary with its flushing messiness. It also would make the system easier to reason about.
For more of this line of thinking take a look at the "Don't mock what you don't own" guideline which I've found very useful.
[pedantic mode on]
In this particular case, or at least the first test case, the unit test doesn't actually need the actual $location service; a mock will suffice to set the expectation (i.e. the path method returning a path)
For clarity, I'd pull the createController function out of the beforeEach method. Actually, in this case you don't even need to have it as a separate method; simply calling $controller will be enough, since one, the controller does not have any behavior on initialization (besides adding a function to the scope), and second because all public methods are assigned to the scope.
Third, the injector can be skipped in favor of just having the appropriate service names in the call to inject.
Same applies to the second unit test. I also wouldn't use the $http service directly from a controller, or mock out http calls using $httpBackend; either use a service that wraps $http calls itself, or ngResource/$resource. Those two can then easily be mocked out in the controller spec (slurpService.scrape(url).andReturn(neatlyParsedResult))
[/pedantic]
In this case it might not be needed, but some controllers have calls that are made on initialisation (like NgResource) which makes harder to use $httpBackend (you have to mock all calls if you want to verify that no calls were left at the end).
I took the article more like best-practice for unit testing controllers.
But truth to be told, it would be nicer if author would explain why to initialise controller in a method etc.
In our project we've ended up with our controller code being defined outside of the .controller call (we're using TypeScript, and someone wanted to use the class syntax). This means that our controllers are accessible directly, and for a unit test, they're just functions we can call.
So we just pass our own mocks in, it's much simpler than trying to use Angular's injector mechanism.
This is a really nice article, it seems you found a similar solution to mine.
The only thing that is more or less difficult about testing Angular ist the boilerplate one has to write to instantiate everything correctly. When writing the code, Angular handles the bootstrapping of the application, but in the tests one has to do it manually.
What's positive about it is that one learns how Angular works internally. I would even say that doing TDD with Angular is actually a lot of fun.
Definitely agree with this. The function passed to the inject() method where you set up your controller and inject mocks seems to have a bunch of repetition in the unit test suites I've been writing. You can use $provide (http://docs.angularjs.org/api/AUTO.$provide) to swap dependencies at the injector level and I'm starting to wonder if doing that would be a lot more repeatable across unit test suites.
Jasmine tests are still hard for me to master (especially the httpBackend stuff), so I really really appreciate posts like this, I guess at the end of the day posts like these also encourage me to write code thats easier to test as well. Thanks :D
In the article's scraping example, a service that works like `Scrape.url('success.com')` could be mocked and sidestep the $http boundary with its flushing messiness. It also would make the system easier to reason about.
For more of this line of thinking take a look at the "Don't mock what you don't own" guideline which I've found very useful.