Search code examples
angularjsdecoratorangular-decorator

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.


Solution

  • 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