Programing

Karma + AngularJS 테스트 내에서 모의 ​​JSON 파일로드

crosscheck 2020. 9. 22. 07:30
반응형

Karma + AngularJS 테스트 내에서 모의 ​​JSON 파일로드


Karma + Jasmine을 사용하여 테스트로 설정된 AngularJS 앱이 있습니다. 큰 JSON 개체를 가져 와서 앱의 나머지 부분에서 더 많이 사용할 수있는 형식으로 변환하고 변환 된 개체를 반환하는 테스트하려는 함수가 있습니다. 그게 다야.

내 테스트를 위해 모의 JSON 콘텐츠 만 포함 된 별도의 JSON 파일 (* .json)을 스크립트없이 갖고 싶습니다. 테스트를 위해 JSON 파일을로드하고 테스트중인 함수로 개체를 펌핑 할 수 있기를 원합니다.

http://dailyjs.com/2013/05/16/angularjs-5/에 설명 된대로 모의 팩토리 내에 JSON을 포함 할 수 있다는 것을 알고 있지만 JSON이 스크립트 내에 포함되지 않기를 원합니다. 파일.

나는 몇 가지를 시도했지만이 분야에서는 상당히 멍청하다. 먼저 Karma가 내 JSON 파일을 포함하도록 설정하여 수행 할 작업을 확인합니다.

files = [
    ...
    'mock-data/**/*.json'
    ...
]

그 결과 :

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

그래서 파일을 "포함"하지 않고 제공하도록 변경했습니다.

files = [
    ...
    { pattern: 'mock-data/**/*.json', included: false }
    ...
]

이제는 제공 만되었으므로 사양 내에서 $ http를 사용하여 파일을로드하려고합니다.

$http('mock-data/two-metrics-with-anomalies.json')

내가받은 사양을 실행했을 때 :

Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json

내 이해로는 $ httpBackend에서 모의 ​​응답을 기대합니다. 그래서 ...이 시점에서 나는 Angular 유틸리티를 사용하여 파일을로드하는 방법을 몰랐기 때문에 적어도 작동 할 수 있는지 확인하기 위해 jQuery를 시도 할 것이라고 생각했습니다.

$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) {
    console.log(data);
}).fail(function(response) {
    console.log(response);
});

결과는 다음과 같습니다.

Chrome 27.0 (Mac) LOG: { readyState: 4,
responseText: 'NOT FOUND',
status: 404,
statusText: 'Not Found' }

Charles에서이 요청을 검사하고 다음 요청을합니다.

/mock-data/two-metrics-with-anomalies.json

Karma에서 "포함"하도록 구성한 나머지 파일은 다음과 같이 요청됩니다.

/base/src/app.js

분명히 Karma는 파일을 제공하기 위해 일종의 기본 디렉토리를 설정하고 있습니다. 그래서 킥을 위해 jquery 데이터 요청을 다음과 같이 변경했습니다.

$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...

그리고 작동합니다! 하지만 지금은 더러워 져서 샤워를해야합니다. 다시 깨끗해 지도록 도와주세요.


각 시드와 함께 각 설정을 사용하고 있습니다. 나는 직선 .json 고정 파일과 jasmine-jquery.js로 이것을 해결했습니다. 다른 사람들은이 대답을 암시했지만 모든 조각을 올바른 위치에 가져 오는 데 시간이 걸렸습니다. 다른 사람에게 도움이되기를 바랍니다.

폴더에 내 json 파일이 /test/mock있고 내 webapp은 /app.

karma.conf.js항목은 다음과 같습니다.

basePath: '../',

files: [
      ... 
      'test/vendor/jasmine-jquery.js',
      'test/unit/**/*.js',

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

내 테스트 파일에는 다음이 있습니다.

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

});

진짜 트릭은 jasmine.getJSONFixtures().fixturesPath='base/test/mock';내가 원래 설정 test/mock했었지만 base거기에 필요 했습니다. 베이스가 없으면 다음과 같은 오류가 발생했습니다.

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

  1. Put karma-read-json.js in your Karma files. Example:

    files = [
      ...
      'bower_components/karma-read-json/karma-read-json.js',
      ...
    ]
    
  2. Make sure your JSON is being served by Karma. Example:

    files = [
      ...
      {pattern: 'json/**/*.json', included: false},
      ...
    ]
    
  3. 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
    ....
}

looks like your solution is the right one but there are 2 things i don't like about it:

  • it uses jasmine
  • it requires new learning curve

i just ran into this problem and had to resolve it quickly as i had no time left for the deadline, and i did the following

my json resource was huge, and i couldn't copy paste it into the test so i had to keep it a separate file - but i decided to keep it as javascript rather than json, and then i simply did:

var someUniqueName = ... the json ...

and i included this into karma conf includes..

i can still mock a backend http response if needed with it.

$httpBackend.whenGET('/some/path').respond(someUniqueName);

i could also write a new angular module to be included here and then change the json resource to be something like

angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );

and then simply inject SomeUniqueName into the test, which looks cleaner.

perhaps even wrap it in a service

angular.module('allTestResources',[]).service('AllTestResources', function AllTestResources( SomeUniqueName , SomeOtherUniqueName, ... ){
   this.resource1 = SomeUniqueName;
   this.resource2 = SomeOtherUniqueName; 
})

this solutions was faster to me, just as clean, and did not require any new learning curve. so i prefer this one.


I was looking for the same thing. I'm going to try this approach. It uses the config files to include the mock data files, but the files are a little more than json, because the json needs to be passed to angular.module('MockDataModule').value and then your unit tests can also load multiple modules and then the value set is available to be injected into the beforeEach inject call.

Also found another approach that looks promising for xhr requests that aren't costly, it's a great post that describes midway testing, which if I understand right lets your controller/service actually retrieve data like in an e2e test, but your midway test has actual access to the controller scope (e2e doesn't I think).


There are Karma preprocessors that work with JSON files also. There is one here:

https://www.npmjs.org/package/karma-ng-json2js-preprocessor

And shameless plug, this is one I developed that has RequireJS support

https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs


You can use the karma-html2js-preprocessor to get the json files added to the __html__ global.

see this answer for details: https://stackoverflow.com/a/22103160/439021


Here is an alternative to Cameron's answer, without the need for jasmine-jquery nor any extra Karma config, to test e.g. an Angular service using $resource :

angular.module('myApp').factory('MyService', function ($resource) {
    var Service = $resource('/:user/resultset');
    return {
        getResultSet: function (user) {
            return Service.get({user: user}).$promise;
        }
    };
});

And the corresponding unit test :

describe('MyServiceTest', function(){
    var $httpBackend, MyService, testResultSet, otherTestData ;

    beforeEach(function (done) {
        module('myApp');
        inject(function ($injector) {
            $httpBackend = $injector.get('$httpBackend');
            MyService = $injector.get('MyService');
        });
        // Loading fixtures
        $.when(
            $.getJSON('base/test/mock/test_resultset.json', function (data) { testResultSet = data; }),
            $.getJSON('base/test/mock/test_other_data.json', function (data) { otherTestData = data; })
        ).then(done);
    });

    it('should have some resultset', function() {
        $httpBackend.expectGET('/blahblahurl/resultset').respond(testResultSet);
        MyService.getResultSet('blahblahurl').then(function (resultSet) {
            expect(resultSet.length).toBe(59);
        });
        $httpBackend.flush();
    });
});

참고URL : https://stackoverflow.com/questions/17370427/loading-a-mock-json-file-within-karmaangularjs-test

반응형