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.