Mocking $http request in e2e test

1,213 views
Skip to first unread message

wakandan wakandan

unread,
Sep 20, 2013, 1:01:45 AM9/20/13
to ang...@googlegroups.com
I want to test this flow for my app: 
  • user logins 
  • he navigates to certain page and perform some actions which change the page's UI and get persisted in DB
I want to test if these UI changes are really happening/showing up the way it should. I don't see how to do a unit test for this - this seems to me more like an e2e test. However of course I don't want to keep hitting my db server everytime these UI changes occurs, so I need to mock these requests to my server.

I don't quite agree with the approach in angularjs docs, as it requires to bootstrap my app with a test module. It means either I need to 
  1. change/replace my index.html for a different ng-app, OR 
  2. have an environment variable to distinguish dev/test and bootstrap the correct module. 

These approach are not ideal and implying a significant overhead. Therefore I'm experimenting this approach (with karma): 
  • Similar to the angular docs above, I create a test module (app_test in app_test.js) which requires my original module (app in app.js). This module will do the mocking (with $httpBackend.whenPOST and so on) something like
phones = [{name: 'phone1'}, {name: 'phone2'}];
$httpBackend.whenGET('/phones').respond(phones);
 
  • This app_test.js file will also include a manual bootstrap code like below at the end
angular.element(document).ready(function() {
  angular.bootstrap(document, ['app_test', 'app']); //<---------important
});
      • I include this app_test.js in my karma config which is to be loaded in the test
      • In the original app.js file where my app is initialized, I run some code (in module.run()) to trigger a POST request which is supposed to return the stub data
      $http.get('/phones').success(function(data, status, headers) {
             console.log('App test post request has returned');
             console.log(data);
           });    
      As you can see, the index.html file isn't touched at all, everything is being setup externally to the app. That's why if this works, it is the ideal approach.
                          But as for the result: When I run this karma test, (probably in initializing phase) these correct stub data is displayed in the console, meaning my mocking was working. However in the real test code within describe() or it(), these mocks request aren't put into play, my requests are being routed to the real server 

                          Can someone please enlighten me on this matter? I have been dwelling into this for few days now. Thanks!



                          Sebastien Vincent

                          unread,
                          Sep 20, 2013, 2:16:27 AM9/20/13
                          to ang...@googlegroups.com
                          I suspect the problem is not 'describe' or it, but 'inject' this is where all the injection magic happens. You should read the code in angular mock, it is pretty easy to understand. If you want to do something fundamentally 
                          different from angular mock, you can simply create your own injector and use it for those tests.

                          I had similar issue recently and what I did is record the json server output once, use it as mock in my unit tests, and then use httpBackend normally.

                          On the other hand what you are describing is midway/e2e test, you should check out protractor. The   ['get' method](https://github.com/angular/protractor/blob/master/lib/protractor.js#L260) let you inject whatever module you like before the page load. 

                          wakandan wakandan

                          unread,
                          Sep 20, 2013, 2:32:57 AM9/20/13
                          to ang...@googlegroups.com
                          I have just observed something weird but can not confirm yet. Could there be any cases where after I mock with $httpBackend, the requests are still going through but the response are being stubbed? My server is logging the request on its log, but my responses (in initialization phase like I said) is the same as what I stubbed. What could be happening here?

                          wakandan wakandan

                          unread,
                          Sep 20, 2013, 2:42:22 AM9/20/13
                          to ang...@googlegroups.com
                          By the way, I was doing e2e test not unit testing. Angular mock doesn't seems to be available for e2e test does it? Or may be I couldn't get it to work

                          Sebastien Vincent

                          unread,
                          Sep 20, 2013, 3:13:53 AM9/20/13
                          to ang...@googlegroups.com
                          I think it is still used in the back, but obviously it is even harder (if possible) to customize.

                          You may want to check this question(http://karma-runner.github.io/0.10/intro/faq.html): 

                          Can I use Karma to do end to end testing ?
                          Karma has primarily been designed for low level (unit) testing. If it's an AngularJS app, you can use Karma with karma-ng-scenario plugin, however we recommend Protractor for high level testing.

                          There must be a reason behind karma not recommending karma for e2e testing.

                          wakandan1

                          unread,
                          Sep 20, 2013, 3:34:21 AM9/20/13
                          to ang...@googlegroups.com
                          I'm looking at protractor now....but I'm still thinking "protractor" is more on the client side right? The issue with mocking is still there I think?

                          Sebastien Vincent

                          unread,
                          Sep 20, 2013, 3:51:23 AM9/20/13
                          to ang...@googlegroups.com
                          Protractor allows for transparent angular mocking. That is the point using protractor. (plus angular specific selector).

                          It's done in the addMockModule/clearMockModules methods.

                          btw If you don't like the WebdriverJs syntax, I wrote my own wd extension which does exactly the same. https://github.com/sebv/wd-tractor

                          wakandan1

                          unread,
                          Sep 20, 2013, 4:14:57 AM9/20/13
                          to ang...@googlegroups.com
                          I might have to switch to protractor if it's the only choice. But it really bugs me the way $http mocks work as I mentioned to you. If you could point me to some direction of how to debug this thing, it should be great. I don't even know where to start looking.

                          Sebastien Vincent

                          unread,
                          Sep 20, 2013, 4:30:24 AM9/20/13
                          to ang...@googlegroups.com
                          I am not sure what exactly happens, it is why I don't use it, but I would start to debug createHttpBackend in angular-scenario.js .
                          Reply all
                          Reply to author
                          Forward
                          0 new messages