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


85

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')...

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

답변:


82

각 시드와 함께 각 설정을 사용하고 있습니다. 나는 직선 .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

1
안녕하세요 Cameron, 오류가 발생합니다 : TypeError : Object # <Object>에는 'getJSONFixtures'메서드가 없습니다 ... 재스민 또는 무언가가 변경 되었습니까?
— Melbourne2991

7
몰랐어요 나는 ... 자스민 - jQuery를 필요를 설치하고 오류가 사라졌다
— Melbourne2991

이 접근 방식은 매우 장황하고 복잡하게 들립니다. 이러한 "고정 장치"가 추가 이점을 제공하는지 여부는 모르겠지만, 원하는 모든 것이 때때로 JSON 파일을 읽는 것이라면 아래 접근 방식이 유리합니다.
— Septagram

43

조명기를 통해 JSON을 제공하는 것이 가장 쉽지만 설정 때문에 쉽게 할 수 없었기 때문에 대체 도우미 함수를 작성했습니다.

저장소

설치

$ bower install karma-read-json --save

  OR

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

  OR

$ yarn add karma-read-json --dev

용법

  1. Karma 파일에 karma-read-json.js를 넣으십시오. 예:

    files = [
      ...
      'bower_components/karma-read-json/karma-read-json.js',
      ...
    ]
    
  2. JSON이 Karma에서 제공되는지 확인하십시오. 예:

    files = [
      ...
      {pattern: 'json/**/*.json', included: false},
      ...
    ]
    
  3. readJSON테스트 에서 함수를 사용하십시오 . 예:

    var valid_respond = readJSON('json/foobar.json');
    $httpBackend.whenGET(/.*/).respond(valid_respond);
    

1
karma-read-json은 jasmine-jquery가 요구하는 bower를 사용하거나 설치할 수없는 경우 훌륭한 옵션입니다. (제 경우에는 Big-corp 정책입니다.) 방금 npm ( npmjs.com/package/karma-read-json )을 통해 설치 했으며 훌륭하게 작동했습니다.
— Melissa Avery-Weir

2
나는 이것이 정자에 의존 할 필요가 없기 때문에 이것이 최선의 접근이라고 생각합니다 ... 카르마 / 자스민과 카르마-읽기 -json. 난 실행하여이 작업을 수행 할 수 있었다 npm install karma-read-json대신bower install karma-read-json
— 에릭 풀러

카르마 접근 방식에 대한 큰 반응-명확한 설명에 감사드립니다!
— nomadoj

A)이 플랫폼에 좀 새로운 것, B) Angular 모듈을 빌드하려고하는 jquery를 사용하지 않습니다. 이것은 나를 위해 잘 작동했습니다. 내 설정이 karma.config.json-> files [] .. karma.config.json에 아무것도 추가하지 않았습니다. 또한 : "const valid_respond = readJSON ( '../ assets / organizations.json'); "여기서 자산은 자산의 표준 위치입니다.
— 차

10

내 테스트 케이스에 외부 데이터를로드하는 솔루션을 찾기 위해 고군분투했습니다. 위 링크 : http://dailyjs.com/2013/05/16/angularjs-5/ 저를 위해 일했습니다.

몇 가지 참고 사항 :

"defaultJSON"은 모의 데이터 파일의 키로 사용해야합니다. defaultJSON을 참조 할 수 있으므로 괜찮습니다.

mockedDashboardJSON.js :

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

그런 다음 테스트 파일에서 :

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
    ....
}

의심 스럽습니다 .. json 파일 당 하나의 모듈이 있습니까? 단일 값에 둘 이상의 값을 추가하려고 시도
— 했기

6

귀하의 솔루션이 올바른 것처럼 보이지만 마음에 들지 않는 두 가지가 있습니다.

  • 재스민을 사용합니다
  • 새로운 학습 곡선이 필요합니다

방금이 문제가 발생하여 마감일까지 남은 시간이 없어서 신속하게 해결해야했고 다음을 수행했습니다.

내 json 리소스가 엄청 나서 테스트에 붙여 넣을 수 없어서 별도의 파일로 보관해야했지만 json이 아닌 자바 스크립트로 유지하기로 결정한 다음 간단히 수행했습니다.

var someUniqueName = ... the json ...

이걸 카르마에 포함 시켰어요 ..

필요한 경우 백엔드 http 응답을 모의 처리 할 수 ​​있습니다.

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

여기에 포함될 새로운 각도 모듈을 작성한 다음 json 리소스를 다음과 같이 변경할 수도 있습니다.

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

그런 다음 SomeUniqueName테스트에 주입 하면 깨끗해 보입니다.

아마도 서비스로 포장 할 수도 있습니다.

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

이 솔루션은 나에게 더 빠르고 깨끗했으며 새로운 학습 곡선이 필요하지 않았습니다. 그래서 나는 이것을 선호합니다.


4

나는 똑같은 것을 찾고 있었다. 나는 이 접근법 을 시도 할 것 입니다. 구성 파일을 사용하여 모의 데이터 파일을 포함하지만 파일은 json보다 약간 큽니다. json을 angular.module ( 'MockDataModule'). value에 전달해야하고 단위 테스트도 여러 모듈을로드 할 수 있기 때문입니다. 그러면 값 세트를 beforeEach 주입 호출에 주입 할 수 있습니다.

또한 비용이 많이 들지 않는 xhr 요청에 대해 유망 해 보이는 또 다른 접근 방식 을 찾았 습니다. 중도 테스트를 설명하는 훌륭한 게시물입니다.이를 이해하면 컨트롤러 / 서비스가 실제로 e2e 테스트와 같은 데이터를 검색 할 수 있지만 중간 테스트에는 실제 컨트롤러 범위에 대한 액세스 (e2e는 생각하지 않습니다).




1

다음은 다음을 사용하여 Angular 서비스를 테스트하기 위해 추가 Karma 구성 이 필요하지 않은 Cameron 의 대답에 대한 대안입니다 .jasmine-jquery$resource

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

그리고 해당 단위 테스트 :

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

$ .when 및 $ .getJSON에서 $는 무엇입니까?
— 매트

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.