Loading a mock JSON file within Karma+AngularJS test

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:

Repository

Install

$ bower install karma-read-json --save

  OR

$ npm install karma-read-json --save-dev

  OR

$ yarn add karma-read-json --dev

Usage

  • 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);
    

  • I've been struggling to find a solution to loading external data into my testcases. The above link: http://dailyjs.com/2013/05/16/angularjs-5/ Worked for me.

    Some notes:

    "defaultJSON" needs to be used as the key in your mock data file, this is fine, as you can just refer to defaultJSON.

    mockedDashboardJSON.js:

    'use strict'
    angular.module('mockedDashboardJSON',[])
    .value('defaultJSON',{
        fakeData1:{'really':'fake2'},
        fakeData2:{'history':'faked'}
    });
    

    Then in your test file:

    beforeEach(module('yourApp','mockedDashboardJSON'));
    var YourControlNameCtrl, scope, $httpBackend, mockedDashboardJSON;
    beforeEach(function(_$httpBackend_,defaultJSON){
        $httpBackend.when('GET','yourAPI/call/here').respond(defaultJSON.fakeData1);
        //Your controller setup 
        ....
    });
    
    it('should test my fake stuff',function(){
        $httpBackend.flush();
        //your test expectation stuff here
        ....
    }
    
    链接地址: http://www.djcxy.com/p/39110.html

    上一篇: AngularJS结束

    下一篇: 在Karma + AngularJS测试中加载模拟JSON文件