I have an AngularJS app set up with tests using Karma+Jasmine. I have a function I want to test that takes a large JSON object, converts it to a format that's more consumable by the rest of the app, and returns that converted object. That's it.
For my tests, I'd like you have separate JSON files (*.json) with mock JSON content only--no script. For the test, I'd like to be able to load the JSON file in and pump the object into the function I'm testing.
I know I can embed the JSON within a mock factory as described here: http://dailyjs.com/2013/05/16/angularjs-5/ but I really want the JSON to not be contained within script--just straight JSON files.
I've tried a few things but I'm fairly noob in this area. First, I set up my Karma to include my JSON file just to see what it would do:
files = [ ... 'mock-data/**/*.json' ... ]
This resulted in:
Chrome 27.0 (Mac) ERROR Uncaught SyntaxError: Unexpected token : at /Users/aaron/p4workspace4/depot/sitecatalyst/branches/anomaly_detection/client/anomaly-detection/mock-data/two-metrics-with-anomalies.json:2
So then I changed it to just serve the files and not "include" them:
files = [ ... { pattern: 'mock-data/**/*.json', included: false } ... ]
Now that they're only served, I thought I'd try to load in the file using $http from within my spec:
$http('mock-data/two-metrics-with-anomalies.json')
When I ran the spec I received:
Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json
Which in my understanding means it expects a mocked response from $httpBackend. So...at this point I didn't know how to load the file using Angular utilities so I thought I'd try jQuery to see if I could at least get that to work:
$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) { console.log(data); }).fail(function(response) { console.log(response); });
This results in:
Chrome 27.0 (Mac) LOG: { readyState: 4, responseText: 'NOT FOUND', status: 404, statusText: 'Not Found' }
I inspect this request in Charles and it's making a request to
/mock-data/two-metrics-with-anomalies.json
Whereas the rest of the files I've configured to be "included" by Karma are being requested at, for example:
/base/src/app.js
Apparently Karma's setting up some sort of base directory to serve the files from. So for kicks I changed my jquery data request to
$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...
And it works! But now I feel dirty and need to take a shower. Help me feel clean again.
I'm using an angular setup with angular seed. I ended up solving this with straight .json fixture files and jasmine-jquery.js. Others had alluded to this answer, but it took me a while to get all the pieces in the right place. I hope this helps someone else.
I have my json files in a folder /test/mock
and my webapp is in /app
.
my karma.conf.js
has these entries (among others):
basePath: '../', files: [ ... 'test/vendor/jasmine-jquery.js', 'test/unit/**/*.js', // fixtures {pattern: 'test/mock/*.json', watched: true, served: true, included: false} ],
then my test file has:
describe('JobsCtrl', function(){ var $httpBackend, createController, scope; beforeEach(inject(function ($injector, $rootScope, $controller) { $httpBackend = $injector.get('$httpBackend'); jasmine.getJSONFixtures().fixturesPath='base/test/mock'; $httpBackend.whenGET('http://blahblahurl/resultset/').respond( getJSONFixture('test_resultset_list.json') ); scope = $rootScope.$new(); $controller('JobsCtrl', {'$scope': scope}); })); it('should have some resultsets', function() { $httpBackend.flush(); expect(scope.result_sets.length).toBe(59); }); });
The real trick was the jasmine.getJSONFixtures().fixturesPath='base/test/mock';
I had originally set it to just test/mock
but it needed the base
in there. Without the base, I got errors like this:
Error: JSONFixture could not be loaded: /test/mock/test_resultset_list.json (status: error, message: undefined) at /Users/camd/gitspace/treeherder-ui/webapp/test/vendor/jasmine-jquery.js:295
Serving JSON via the fixture is the easiest but because of our setup we couldn't do that easily so I wrote an alternative helper function:
$ bower install karma-read-json --save OR $ npm install karma-read-json --save-dev OR $ yarn add karma-read-json --dev
Put karma-read-json.js in your Karma files. Example:
files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ]
Make sure your JSON is being served by Karma. Example:
files = [ ... {pattern: 'json/**/*.json', included: false}, ... ]
Use the readJSON
function in your tests. Example:
var valid_respond = readJSON('json/foobar.json'); $httpBackend.whenGET(/.*/).respond(valid_respond);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With