Fixtures in in karma unit test.

832 views
Skip to first unread message

Sebastien Vincent

unread,
Sep 10, 2013, 5:44:04 AM9/10/13
to ang...@googlegroups.com
Hi,

I've been googling around trying to figure out this, but none of the solutions I found were very satisfying.

This is what I want to do, in unit test, not e2e.

- Make fixtures available via http using this in karma.conf.

      {pattern: 'test/fixtures/**/*.json', watched: false, served: true, included: false},

- Then when I try to access this using the $http service, I found out that $httpBackend is blocking access to this files, and there seem to be no way to relax this policy.

- So I had to use an alternative js lib to be able to do a simple GET request(reqwest or zepto in my case, since I am not using jquery, other people were using jasmine-jquery).

I am wondering if I am missing something here, since the $http module is still --nearly--- at hand, that would be easier to be able to use it. Even easier would be to be able to proxy the $httpBackend response directly to a fixture.

Cheers.

Seb.

Sebastien Vincent

unread,
Sep 10, 2013, 7:22:07 AM9/10/13
to ang...@googlegroups.com
Answering my own question since I went to the bottom of this:

It all happens in the 'inject' function provided by angular mock. This is were the $httpBackend is injected. So you need to load your fixtures before that using the regular $http. You need to build a fixture helper and retrieve http like this (or even better create a small module to do that):
      var injector = angular.injector(['ng']);
      var $http = injector.get('$http');

Still would be nice to have a smarter $httpBackend.

Seb.

Michael Bielski

unread,
Sep 10, 2013, 10:34:49 AM9/10/13
to ang...@googlegroups.com
You probably shouldn't be using $http in unit tests, even for what you are doing. $httpBackend is there to MOCK what an $http request would do, not provide a platform to spy from or serve files from. If you need the information from a .JSON file you should mock it and make that mock available to your tests. Unit tests generally are about testing if the smallest parts of code are doing what you expect them to when they are given both the right and wrong information, and actively pulling something in via $http when it can be mocked easily (and this would be especially true of JSON) seems to go against that.

Sebastien Vincent

unread,
Sep 10, 2013, 11:16:42 AM9/10/13
to ang...@googlegroups.com
Thanks for your answer.

I see your point but to my opinion transforming a json fixture into a js mock does not seem like a good solution. For instance, if I were doing node.js test, I would simply upload the json rather than transforming it into a js object, so why should it be different with browser test, specially since the Karma test runner provides the feature?

I've already figured out a way to do it here: https://gist.github.com/sebv/6509524 . All that was needed was to load the fixture manager outside the spec runner context. 

ThomasBurleson

unread,
Sep 10, 2013, 3:12:02 PM9/10/13
to ang...@googlegroups.com
Sebastien,

You have discovered an oddly-kept `secret`.  Karma uses 
  • a custom implementation special Jasmine Spec framework
  • Angular-Mocks - which overrides $http to prevent all real XHR calls. 
Most of the AngularJS community insists this is not necessary; as mocks can be used to test your components.  But what if you want to test with live remote dataservices? And you cannot just remove `angular-mocks` because it publish gobal functions `module()` and `inject()` for use within your test cases; it also hooks into the `beforeEach()` and `afterEach()` setup/teardown methods.

I created a special version of angular-mocks called `angular-spec.js`. Angular-Spec provides the above mentioned global functions but does NOT override $http.
This means you can make REAL service calls with your tests.

I also recommend you check out `jasmine-as-promised` which extends the Jasmine Spec framework with transparent support for AngularJS promises.

Sebastien Vincent

unread,
Sep 10, 2013, 10:36:26 PM9/10/13
to ang...@googlegroups.com
Thomas,

Maybe you could try to reinject your service from a separate injector, from within the inject method, in order to override the service using the mocked $http with one using the real $http. Then you should be able to use $http without modifying ngMock...but that is getting a bit tricky ;).
Reply all
Reply to author
Forward
0 new messages