Karma + AngularJS testi içinde sahte bir JSON dosyası yükleme


85

Karma + Jasmine kullanarak testlerle kurulmuş bir AngularJS uygulamam var. Test etmek istediğim, büyük bir JSON nesnesi alan, onu uygulamanın geri kalanı tarafından daha tüketilebilir bir biçime dönüştüren ve dönüştürülen nesneyi döndüren bir işlevim var. Bu kadar.

Testlerim için, yalnızca sahte JSON içeriğine sahip ayrı JSON dosyalarınızın (* .json) olmasını istiyorum - komut dosyası yok. Test için, JSON dosyasını yükleyebilmek ve nesneyi test ettiğim işleve pompalayabilmek istiyorum.

JSON'u burada açıklandığı gibi bir sahte fabrikaya yerleştirebileceğimi biliyorum: http://dailyjs.com/2013/05/16/angularjs-5/ ancak JSON'un komut dosyası içinde yer almamasını gerçekten istiyorum - sadece düz JSON Dosyalar.

Birkaç şey denedim ama bu alanda oldukça acemiyim. İlk olarak, ne yapacağını görmek için Karma'mı JSON dosyamı içerecek şekilde ayarladım:

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

Bu sonuçlandı:

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

Bu yüzden, onları "içermek" yerine yalnızca dosyaları sunmak için değiştirdim:

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

Artık yalnızca sunulduğuna göre, dosyamı $ http kullanarak benim spesifikasyonumdan yüklemeye çalışacağımı düşündüm:

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

Aldığım spesifikasyonu çalıştırdığımda:

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

Benim anlayışıma göre, $ httpBackend'den alay konusu bir yanıt beklediği anlamına geliyor. Yani ... bu noktada Angular yardımcı programlarını kullanarak dosyayı nasıl yükleyeceğimi bilmiyordum, bu yüzden en azından işe yarayıp yaramayacağını görmek için jQuery'yi deneyeceğimi düşündüm:

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

Bunun sonucu:

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

Bu isteği Charles'ta inceliyorum ve bu bir talepte bulunuyor

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

Karma tarafından "dahil edilmek" üzere yapılandırdığım dosyaların geri kalanı şurada istenirken, örneğin:

/base/src/app.js

Görünüşe göre Karma dosyalara hizmet vermesi için bir tür temel dizin kuruyor. Bu yüzden tekmeler için jquery veri isteğimi şu şekilde değiştirdim:

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

Ve çalışıyor! Ama şimdi kendimi kirli hissediyorum ve duş almam gerekiyor. Tekrar temiz hissetmeme yardım et.

Yanıtlar:


82

Açılı çekirdekli açısal bir kurulum kullanıyorum. Bunu düz .json fikstür dosyaları ve jasmine-jquery.js ile çözdüm. Diğerleri bu yanıtı ima etmişti, ancak tüm parçaları doğru yere yerleştirmem biraz zaman aldı. Umarım bunun bir başkasına yardımı olur.

Json dosyalarım bir klasörde /test/mockve web uygulamam içinde /app.

bende karma.conf.jsşu girişler var (diğerleri arasında):

basePath: '../',

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

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

daha sonra test dosyamda:

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

});

Asıl numara, jasmine.getJSONFixtures().fixturesPath='base/test/mock'; başlangıçta onu ayarladığımdı test/mockama baseoraya ihtiyacı vardı. Taban olmadan şu tür hatalar alıyorum:

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
Merhaba Cameron, bir hata alıyorum: TypeError: Object # <Object> 'getJSONFixtures' yöntemine sahip değil ... yasemin veya başka bir şey için değişiklik yapıldı mı?
Melbourne2991

7
yasemin-jquery istediğimi fark etmemiştim ... yükledim ve hata ortadan kalktı
Melbourne2991

Bu yaklaşım kulağa oldukça ayrıntılı ve karmaşık geliyor ... Bu "fikstürlerin" ek faydalar sağlayıp sağlamadığını bilmiyorum, ancak aşağıdaki yaklaşım, tek istediğiniz zaman zaman bir JSON dosyasını okumaksa kazanır.
Eylül

43

Fikstür aracılığıyla JSON'a hizmet vermek en kolayıdır, ancak kurulumumuz nedeniyle bunu kolayca yapamadık, bu yüzden alternatif bir yardımcı işlev yazdım:

Depo

Yüklemek

$ bower install karma-read-json --save

  OR

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

  OR

$ yarn add karma-read-json --dev

Kullanım

  1. Karma-read-json.js dosyasını Karma dosyalarınıza koyun. Misal:

    files = [
      ...
      'bower_components/karma-read-json/karma-read-json.js',
      ...
    ]
    
  2. JSON'nuzun Karma tarafından sunulduğundan emin olun. Misal:

    files = [
      ...
      {pattern: 'json/**/*.json', included: false},
      ...
    ]
    
  3. readJSONFonksiyonu testlerinizde kullanın . Misal:

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

1
karma-read-json, yasemin-jquery'nin gerektirdiği çardağı kullanamıyorsanız veya kuramıyorsanız harika bir seçenektir. (Benim durumumda büyük şirket politikası.) Npm ( npmjs.com/package/karma-read-json ) aracılığıyla yeni yükledim ve harika çalıştı.
Melissa Avery-Weir

2
Bunun en iyi yaklaşım olduğunu düşünüyorum çünkü kameriye bağımlılığı gerektirmiyor ... sadece karma / yasemin ve karma-read-json. Bunu npm install karma-read-jsonyerine koşarak bile yapabildimbower install karma-read-json
Eric Fuller

Karma yaklaşımı için harika yanıt - net açıklama için teşekkürler!
nomadoj

A) bu platform için biraz yeni, B) bir Açısal Modül oluşturmaya çalışırken jquery kullanmamak. Bu benim için iyi çalıştı. kurulumum karma.config.json -> dosyalarında [] tıkandı .. karma.config.json'a hiçbir şey eklemedim .. Ayrıca: "const valid_respond = readJSON ('../ assets / organization.json'); "Varlıkların, varlıkların standart konumu olduğu.
2019

10

Dış verileri test olaylarıma yüklemek için bir çözüm bulmakta zorlanıyorum. Yukarıdaki bağlantı: http://dailyjs.com/2013/05/16/angularjs-5/ Benim için çalıştı.

Bazı notlar:

Sahte veri dosyanızda anahtar olarak "defaultJSON" kullanılması gerekir, bu sorun değildir, çünkü defaultJSON'a başvurabilirsiniz.

mockedDashboardJSON.js:

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

Ardından test dosyanızda:

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

Bir şüphem var .. json dosyası başına bir modül olacak mı? çünkü tek değerlere birden fazla değer eklemeyi denedim, ikinci json için bilinmeyen sağlayıcı hatası alıyorum
Pawan

6

Görünüşe göre çözümünüz doğru çözüm ama hoşuma gitmeyen 2 şey var:

  • yasemin kullanıyor
  • yeni bir öğrenme eğrisi gerektirir

bu sorunla karşılaştım ve son teslim tarihine kadar vaktim olmadığı için çabucak çözmek zorunda kaldım ve aşağıdakileri yaptım

json kaynağım çok büyüktü ve onu kopyalayıp teste yapıştıramadım, bu yüzden ayrı bir dosya tutmak zorunda kaldım - ancak onu json yerine javascript olarak tutmaya karar verdim ve sonra basitçe yaptım:

var someUniqueName = ... the json ...

ve bunu karma conf içerir ..

Yine de gerekirse bir arka uç http yanıtıyla alay edebilirim.

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

Ayrıca buraya dahil edilecek yeni bir açısal modül yazabilir ve ardından json kaynağını şu şekilde değiştirebilirim:

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

ve sonra daha SomeUniqueNametemiz görünen teste enjekte edin.

belki bir servise bile sarabilirsin

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

bu çözümler benim için daha hızlıydı, aynı temizdi ve yeni bir öğrenme eğrisi gerektirmiyordu. bu yüzden bunu tercih ederim.


4

Ben de aynı şeyi arıyordum. Bu yaklaşımı deneyeceğim . Sahte veri dosyalarını dahil etmek için yapılandırma dosyalarını kullanır, ancak dosyalar json'dan biraz daha fazladır, çünkü json'un angular.module ('MockDataModule') değerine aktarılması gerekir ve ardından birim testleriniz birden fazla modül yükleyebilir ve daha sonra, set değeri her bir önceki çağrıya enjekte edilebilir.

Ayrıca maliyetli olmayan xhr istekleri için umut verici görünen başka bir yaklaşım buldum , bu, orta yol testini açıklayan harika bir gönderi, doğru anlarsam denetleyicinizin / hizmetinizin bir e2e testindeki gibi verileri gerçekten almasını sağlar, ancak orta yol testiniz gerçek denetleyici kapsamına erişim (e2e sanmıyorum).




1

Aşağıda, Cameron'ın cevabına, jasmine-jqueryfazladan Karma yapılandırmasına veya herhangi bir ekstra Karma yapılandırmasına gerek kalmadan, örneğin bir Angular servisini kullanarak test etmek için bir alternatif $resource:

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

Ve ilgili birim testi:

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 ve $ .getJSON'daki gibi $ nedir?
Matt

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.