Karma + AngularJSテスト内のモックJSONファイルの読み込み


85

Karma + Jasmineを使用したテストでAngularJSアプリをセットアップしました。大きなJSONオブジェクトを受け取り、それをアプリの他の部分でより使いやすい形式に変換し、変換されたオブジェクトを返す、テストしたい関数があります。それでおしまい。

私のテストでは、モックJSONコンテンツのみを含む個別のJSONファイル(* .json)が必要です。スクリプトはありません。テストでは、JSONファイルを読み込んで、テストしている関数にオブジェクトを送り込めるようにしたいと思います。

http://dailyjs.com/2013/05/16/angularjs-5/で説明されているように、モックファクトリ内にJSONを埋め込むことができることはわかっていますが、JSONをスクリプトに含めないでください。ストレートJSONだけです。ファイル。

私はいくつかのことを試しましたが、私はこの分野ではかなり初心者です。まず、JSONファイルを含めるようにKarmaを設定して、それが何をするかを確認します。

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

私はチャールズでこのリクエストを検査し、

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

Karmaによって「インクルード」されるように構成した残りのファイルは、たとえば次の場所で要求されています。

/base/src/app.js

どうやらカルマはファイルを提供するためにある種のベースディレクトリを設定しているようです。キックの場合、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/mockbase、そこにそれが必要だったということでした。ベースがないと、次のようなエラーが発生しました。

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
こんにちはキャメロン、私はエラーを受け取ります:TypeError:オブジェクト#<オブジェクト>にはメソッド 'getJSONFixtures'がありません...ジャスミンなどに変更が加えられましたか?
Melbourne2991

7
jasmine-jqueryが必要だと気づかなかった...インストールしてエラーが消えた
Melbourne2991

このアプローチは非常に冗長で複雑に聞こえます...これらの「フィクスチャ」が追加の利点を提供するかどうかはわかりませんが、JSONファイルを時々読み取るだけであれば、以下のアプローチが有効です。
セプタグラム2017年

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)を介してインストールしたところ、うまく機能しました。
メリッサエイブリー-ウィアー

2
バウアーに依存する必要がないので、これが最善のアプローチだと思います... karma / jasmineとkarma-read-jsonだけです。npm install karma-read-json代わりに実行することでこれを行うこともできましたbower install karma-read-json
Eric Fuller

カルマアプローチに対する素晴らしい反応-明確な説明に感謝します!
nomadoj 2016

A)このプラットフォームに少し新しい、B)Angularモジュールを構築しようとしてjqueryを使用していない。これは私にとってうまくいきました。私のセットアップはkarma.config.json-> files [] ..に詰まっています。karma.config.jsonに何も追加しませんでした。また: "const valid_respond = readJSON( '../ assets / organizations.json'); 「ここで、assetsはアセットの標準的な場所です。
terary

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ファイルごとに1つのモジュールがありますか?単一の値に複数の値を追加しようとしたため、2番目のjsonで不明なプロバイダーエラーが発生しました
Pawan 2016

6

あなたの解決策は正しいように見えますが、私がそれについて好きではないことが2つあります:

  • ジャスミンを使用しています
  • 新しい学習曲線が必要です

締め切りに間に合わなかったので、この問題に遭遇し、すぐに解決する必要がありました。次のことを行いました。

私のjsonリソースは巨大で、コピーしてテストに貼り付けることができなかったため、別のファイルを保持する必要がありましたが、jsonではなくjavascriptとして保持することにし、単純に次のようにしました。

var someUniqueName = ... the json ...

そして私はこれをカルマconfに含めました。

必要に応じて、バックエンドのhttp応答をモックすることもできます。

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

ここに含める新しいAngularモジュールを作成して、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をangular.module( 'MockDataModule')。valueに渡す必要があるため、ファイルはjsonより少し多くなります。その後、単体テストで複数のモジュールをロードすることもできます。次に、値セットを使用して、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.