Edit: (updated Feb 28, 2014)
I did a previous entry on unit testing controllers (it also covers the basic set up for Jasmine testing).That's probably the most important thing you can unit test, but what about services? Those are the piece you're using to do things like talk to other controllers, send AJAX requests, and/or interact with any dependency in your Angular application.
Testing services isn't exactly straight forward, at least if you're coming from the mindset of testing controllers. It can get a little more convoluted when your service has dependencies on other services. How can you test it in isolation from the other pieces?
Basic service testing
To start off, let's look at an extremely basic service. Something that just does something really minor, but you use this functionality everywhere, so you'd like it to be injectable. Below you'll see a really simple service that just manipulates some text and returns it.
To test this, what we need to do is simply inject it with angular-mocks inject() helper function in our beforeEach() call, then we can make calls to it and test the outcomes:
Testing a service with $http using $httpBackend
Things get a little trickier when we want to test a service that depends on other services, particularly in the case of $http. Fortunately, $http relies on $httpBackend in Angular, and angular-mocks.js automatically provides a mock $httpBackend for you.
So if we were to look at a simple service that gets data over $http, it might look something like this:
The process here is fairly similar to what we did above. Since angular-mocks.js has already provided the mock $httpBackend, we can use some functions it's added to test how $http is being used, and even to mock what it returns. We simply need to inject the $httpBackend and make the appropriate calls to it's newly provided test helper functions, such as when(), expectGET() or expectPOST(). We also need to add an afterEach() call to assert that our expectations set in $httpBackend were met.:
Providing custom mocks
Finally, you're likely to have the need to provide mocks to other services in order to test your service in isolation. For example, if you have a service foo that depends on service bar, you may want to inject a mock to bar so you can test foo in isolation from bar. So presuming we have the following service, and we want to test myService in isolation from foo:
Providing mocks is as easy as adding an anonymous function to the module() call that loads your module, that set up values in it's provider. At the same point in your beforeEach() that you're loading the module you're testing, just add a second parameter that is a function that sets up your mock (replacing whatever service was there before).
That should be all you require to test your services. Test well, test thoroughly, test red-green if you can. If you're testing something that injects $http, use $httpBackend where you can, but you can, of course, mock $http yourself if you wanted to. The world is your oyster here, as long as your tests cover your code well.
And, since I try to provide something for people to play with, here is a working plunk demonstrating the techniques I wrote about above.