Đang tải một tệp JSON giả trong bài kiểm tra Karma + AngularJS


85

Tôi có một ứng dụng AngularJS được thiết lập với các bài kiểm tra bằng Karma + Jasmine. Tôi có một chức năng tôi muốn thử nghiệm lấy một đối tượng JSON lớn, chuyển đổi nó sang định dạng dễ tiêu thụ hơn bởi phần còn lại của ứng dụng và trả về đối tượng đã chuyển đổi đó. Đó là nó.

Đối với các thử nghiệm của tôi, tôi muốn bạn có các tệp JSON riêng biệt (* .json) chỉ với nội dung JSON giả - không có tập lệnh. Đối với thử nghiệm, tôi muốn có thể tải tệp JSON vào và bơm đối tượng vào chức năng tôi đang thử nghiệm.

Tôi biết mình có thể nhúng JSON vào trong một nhà máy giả như được mô tả ở đây: http://dailyjs.com/2013/05/16/angularjs-5/ nhưng tôi thực sự muốn JSON không được chứa trong tập lệnh - chỉ cần JSON thẳng các tập tin.

Tôi đã thử một vài thứ nhưng tôi khá là không quen trong lĩnh vực này. Đầu tiên, tôi thiết lập Karma để bao gồm tệp JSON của mình chỉ để xem nó sẽ làm gì:

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

Điều này dẫn đến:

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

Vì vậy, sau đó tôi đã thay đổi nó để chỉ phân phát các tệp và không "bao gồm" chúng:

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

Bây giờ chúng chỉ được phục vụ, tôi nghĩ tôi sẽ cố gắng tải vào tệp bằng cách sử dụng $ http từ trong thông số kỹ thuật của tôi:

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

Khi tôi chạy thông số kỹ thuật, tôi nhận được:

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

Theo hiểu biết của tôi, điều đó có nghĩa là nó mong đợi một phản hồi chế giễu từ $ httpBackend. Vì vậy, ... tại thời điểm này, tôi không biết làm thế nào để tải tệp bằng các tiện ích Angular nên tôi nghĩ tôi sẽ thử jQuery để xem liệu ít nhất tôi có thể làm cho nó hoạt động hay không:

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

Kết quả này trong:

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

Tôi kiểm tra yêu cầu này ở Charles và nó đang đưa ra yêu cầu

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

Trong khi phần còn lại của các tệp mà tôi đã định cấu hình để được "đưa vào" bởi Karma đang được yêu cầu tại, ví dụ:

/base/src/app.js

Rõ ràng Karma đang thiết lập một số loại thư mục cơ sở để phục vụ các tệp từ đó. Vì vậy, đối với các cú hích, tôi đã thay đổi yêu cầu dữ liệu jquery của mình thành

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

Và nó hoạt động! Nhưng bây giờ tôi cảm thấy bẩn và cần đi tắm. Giúp tôi cảm thấy sạch sẽ trở lại.

Câu trả lời:


82

Tôi đang sử dụng thiết lập góc với hạt giống góc. Tôi đã giải quyết vấn đề này bằng các tệp cố định .json thẳng và jasmine-jquery.js. Những người khác đã ám chỉ câu trả lời này, nhưng tôi phải mất một lúc để đưa tất cả các phần vào đúng vị trí. Tôi mong điều này giúp được người nào khác.

Tôi có các tệp json của mình trong một thư mục /test/mockvà ứng dụng web của tôi đang ở trong đó /app.

của tôi karma.conf.jscó những mục này (trong số những mục khác):

basePath: '../',

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

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

thì tệp thử nghiệm của tôi có:

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

});

Bí quyết thực sự là jasmine.getJSONFixtures().fixturesPath='base/test/mock'; tôi đã đặt nó ngay từ đầu test/mocknhưng nó cần baseở đó. Nếu không có cơ sở, tôi gặp lỗi như sau:

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
Xin chào Cameron, tôi gặp lỗi: TypeError: Object # <Object> không có phương thức 'getJSONFixtures' ... có một thay đổi nào được thực hiện đối với jasmine hay gì đó không?
Melbourne2991

7
đã không nhận ra tôi cần hoa nhài-jquery ... cài đặt nó và lỗi đã biến mất
Melbourne2991

Cách tiếp cận này nghe có vẻ khá dài dòng và phức tạp ... Tôi không biết liệu những "đồ đạc" này có cung cấp thêm lợi ích không, nhưng cách tiếp cận dưới đây sẽ thành công nếu tất cả những gì bạn muốn là thỉnh thoảng đọc một tệp JSON.
Septagram

43

Cung cấp JSON thông qua vật cố định là dễ nhất nhưng do thiết lập của chúng tôi, chúng tôi không thể làm điều đó dễ dàng, vì vậy tôi đã viết một hàm trợ giúp thay thế:

Kho

Tải về

$ bower install karma-read-json --save

  OR

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

  OR

$ yarn add karma-read-json --dev

Sử dụng

  1. Đặt karma-read-json.js trong các tệp Karma của bạn. Thí dụ:

    files = [
      ...
      'bower_components/karma-read-json/karma-read-json.js',
      ...
    ]
    
  2. Đảm bảo rằng JSON của bạn đang được Karma phân phát. Thí dụ:

    files = [
      ...
      {pattern: 'json/**/*.json', included: false},
      ...
    ]
    
  3. Sử dụng readJSONchức năng trong các bài kiểm tra của bạn. Thí dụ:

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

1
karma-read-json là một lựa chọn tuyệt vời nếu bạn không thể sử dụng hoặc cài đặt bower, mà jasmine-jquery yêu cầu. (Trong trường hợp của tôi là chính sách Big-corp.) Tôi vừa cài đặt qua npm ( npmjs.com/package/karma-read-json ) và nó hoạt động tốt.
Melissa Avery-Weir

2
Tôi nghĩ đây là cách tiếp cận tốt nhất vì nó không yêu cầu phụ thuộc vào bower ... chỉ cần karma / jasmine và karma-read-json. Tôi thậm chí còn có thể làm điều này bằng cách chạy npm install karma-read-jsonthay vìbower install karma-read-json
Eric Fuller

Phản hồi tuyệt vời cho cách tiếp cận nghiệp - cảm ơn vì mô tả rõ ràng!
nomadoj

A) khá mới với nền tảng này, B) không sử dụng jquery khi cố gắng xây dựng Mô-đun Angular. Điều này làm việc tốt cho tôi. thiết lập của tôi bị nghẹt thở trên các tệp karma.config.json -> [] .. Tôi không thêm gì trong karma.config.json .. Ngoài ra: "const valid_respond = readJSON ('../ asset / organization.json'); "trong đó tài sản là vị trí tiêu chuẩn của tài sản.
terary

10

Tôi đang loay hoay tìm giải pháp để tải dữ liệu bên ngoài vào tủ thử nghiệm của mình. Liên kết trên: http://dailyjs.com/2013/05/16/angularjs-5/ Đã làm việc cho tôi.

Một số lưu ý:

"defaultJSON" cần được sử dụng làm khóa trong tệp dữ liệu giả của bạn, điều này là tốt, vì bạn có thể chỉ tham khảo defaultJSON.

mockedDashboardJSON.js:

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

Sau đó, trong tệp thử nghiệm của bạn:

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

Tôi có nghi ngờ .. Sẽ có một mô-đun cho mỗi tệp json? vì tôi đã cố gắng thêm nhiều hơn một giá trị trên các giá trị duy nhất, tôi nhận được lỗi nhà cung cấp chưa được biết cho json thứ hai
Pawan

6

Có vẻ như giải pháp của bạn là đúng nhưng có 2 điều tôi không thích ở nó:

  • nó sử dụng hoa nhài
  • nó yêu cầu đường cong học tập mới

Tôi vừa gặp phải vấn đề này và phải giải quyết nó nhanh chóng vì tôi không còn thời gian cho thời hạn, và tôi đã làm như sau

tài nguyên json của tôi rất lớn và tôi không thể sao chép, dán nó vào thử nghiệm nên tôi phải giữ nó thành một tệp riêng biệt - nhưng tôi quyết định giữ nó dưới dạng javascript thay vì json, và sau đó tôi chỉ đơn giản là:

var someUniqueName = ... the json ...

và tôi đã đưa điều này vào tâm sự nghiệp bao gồm ..

tôi vẫn có thể giả lập phản hồi http phụ trợ nếu cần với nó.

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

tôi cũng có thể viết một mô-đun góc cạnh mới để đưa vào đây và sau đó thay đổi tài nguyên json thành một thứ gì đó giống như

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

và sau đó chỉ cần đưa SomeUniqueNamevào thử nghiệm, nó trông sạch hơn.

thậm chí có thể gói nó trong một dịch vụ

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

giải pháp này nhanh hơn đối với tôi, cũng sạch sẽ và không yêu cầu bất kỳ đường học tập mới nào. vì vậy tôi thích cái này hơn.


4

Tôi đã tìm kiếm điều tương tự. Tôi sẽ thử cách tiếp cận này . Nó sử dụng các tệp cấu hình để bao gồm các tệp dữ liệu giả, nhưng các tệp này nhiều hơn một chút so với json, vì json cần phải được chuyển đến giá trị angle.module ('MockDataModule') và sau đó các bài kiểm tra đơn vị của bạn cũng có thể tải nhiều mô-đun và sau đó tập giá trị có sẵn để được đưa vào lệnh gọi beforeEach.

Cũng đã tìm thấy một cách tiếp cận khác có vẻ hứa hẹn cho các yêu cầu xhr mà không tốn kém, đó là một bài đăng tuyệt vời mô tả thử nghiệm giữa chừng, nếu tôi hiểu đúng thì cho phép bộ điều khiển / dịch vụ của bạn thực sự truy xuất dữ liệu như trong thử nghiệm e2e, nhưng thử nghiệm giữa chừng của bạn có thực tế truy cập vào phạm vi bộ điều khiển (tôi không nghĩ vậy).




1

Đây là một giải pháp thay thế cho câu trả lời của Cameron , mà không cần jasmine-jqueryhoặc bất kỳ cấu hình Karma bổ sung nào, để kiểm tra ví dụ: một dịch vụ Angular bằng cách sử dụng $resource:

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

Và bài kiểm tra đơn vị tương ứng:

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

$ Dưới dạng $ .when và $ .getJSON là gì?
Matt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.