2015-08-11 19 views
5

config.json dosyasının yüklenmesinden sorumlu bir açısal hizmetim var. Ben çalışma aşamamda aramak istiyorum, bu yüzden json'u $ rootContext'a ayarladım ve bundan dolayı herkes için gelecekte mevcut.

Temelde, bu bende ne olduğunu:

angular.module('app.core', []).run(function(CoreRun) { 
    CoreRun.run(); 
}); 

benim CoreRun hizmetidir Nerede:

angular.module('app.core').factory('CoreRun', CoreRun); 

CoreRun.$inject = ['$rootScope', 'config']; 

function CoreRun($rootScope, config) { 
    function run() { 
    config.load().then(function(response) { 
     $rootScope.config = response.data; 
    }); 
    }  
    return { 
    run: run 
    }; 
} 

Bu iyi çalışır ve ben testi bunu çalıştığınızda sorun çıkageldi . Yapılandırma hizmetinde casusluk yapmak istiyorum, bu yüzden sahte bir söz verir. Ancak, sınama aşamasında sınama aşamamdan beri yapamıyorum, hizmetler kullanılamıyor ve $ q enjekte edemiyorum.

Yapılandırma şablonumla dalga geçmek zorunda olduğum tek şansı görebildiğim kadarıyla, yapılandırma aşamasında, çalıştırma bloğu tarafından çağrıldığından beri var.

Şimdiye kadar bulduğum tek yol, gerçekten sevmediğim jQuery'yi kullanarak sözümü üretmektir.

beforeEach(module('app.core')); 

var configSample; 

beforeEach(module(function ($provide) { 
    config = jasmine.createSpyObj('config', [ 'load' ]); 
    config.load.and.callFake(function() { 
    configSample = { baseUrl: 'someurl' };   
    return jQuery.Deferred().resolve({data: configSample}).promise(); 
    }); 
    provide.value('config', config); 
})); 

it('Should load configuration using the correspond service', function() { 
    // assert 
    expect(config.load).toHaveBeenCalled(); 
    expect($rootScope.config).toBe(configSample); 
}); 

Daha doğru bir çözüm bulmak için bir yolu var mı?

DÜZENLEME: Muhtemelen bu sadece bir koşumun blok çalıştırdığımda bir sorun olduğunu belirtti.

+1

[Muhtemelen .config bölümüne en fazla $ q ve $ http enjekte edilebilir] olası kopyası (http://stackoverflow.com/questions/20626514/can-q-and-http-be-injected -in-the-config-section) – Constantine

+0

Benzer ama tamamen farklı görünüyor. Önerdiğiniz, gerçek bir modülün yapılandırma aşamasında $ q enjekte etmekle ilgilidir. Bu, bir ünite testinin konfigürasyon fazı sırasında bir çalışma bloğundaki $ q'lık enjekte etmek ile ilgilidir, bu yüzden, run bloğunuzu test edebilmek için alay edebilirsiniz. – jbernal

cevap

3

$q numaralı iğneyi doğru şekilde enjekte etmek mümkün olmadığından, run() bloğunuzdaki işlev hemen tetiklenir. run() bloğu, Angular içinde bir yapılandırma aşaması olarak kabul edilir, bu nedenle inject() testlerde yalnızca yapılandırma bloklarından sonra çalışır, bu nedenle inject()$q testte bile olsa,, çünkü ilk olarak run() yürütür.

Bir süre sonra çok kirli bir çözümle module(function ($provide) {}) bloğunda $q elde edebildim. Fikir, ek bir açısal modül oluşturmak ve uygulama modülünüzden önce sınamaya dahil etmektir. Bu ekstra modülün, $q genel bir ad alanına yayınlayacağı bir run() bloğuna sahip olması gerekir. Enjektör ilk olarak ek modülün run() ve ardından uygulama modülünün run() numarasını arayacaktır.

angular.module('global $q', []).run(function ($q) { 
    window.$q = $q; 
}); 

describe('test', function() { 

    beforeEach(function() { 

     module('global $q'); 

     module('app.core'); 

     module(function ($provide) { 
      console.log(window.$q); // exists 
     }); 

     inject(); 

    }); 
}); 

Bu ek modül, özellik dosyalarından önce test paketi için ayrı bir dosya olarak eklenebilir. Modülü, testlerin yapıldığı aynı dosyaya koyarsanız, olayın global window değişkenini değil, yalnızca bir dosya içindeki bir değişkeni kullanması gerekmez.

Here is a working plunker (a "script.js" dosyasını bakınız)

İlk çözeltisi (sorunu çözmüyor): Aslında bu durumda $q kullanabilirsiniz

, ama bunu enjekte etmek zorunda bir test dosyasına. Burada, test altındaki bir birime gerçekten enjekte etmeyeceksiniz, ancak doğrudan testin içinde kullanabilmek için bir test dosyasına.Yani aslında test altındaki bir birim türüne bağlı değildir:

// variable that holds injected $q service 
var $q; 

beforeEach(module(function ($provide) { 
    config = jasmine.createSpyObj('config', [ 'load' ]); 

    config.load.and.callFake(function() { 
     var configSample = { baseUrl: 'someurl' }; 

     // create new deferred obj 
     var deferred = $q.defer(); 

     // resolve promise 
     deferred.resolve({ data: configSample }); 

     // return promise 
     return deferred.promise; 
    }); 

    provide.value('config', config); 
})); 

// inject $q service and save it to global (for spec) variable 
// to be able to access it from mocks 
beforeEach(inject(function (_$q_) { 
    $q = _$q_; 
})); 

Kaynaklar:

Ve bir not : yapılandırması ve yapılandırması faz iki farklı şeydir. Config block, yalnızca sağlayıcıları kullanmanıza izin verir, ancak numaralı blokta, hemen hemen her şeyi (sağlayıcılar hariç) enjekte edebilirsiniz. Daha fazla bilgi here - Module Loading & Dependencies

+0

Evet, tabiki. Aralarındaki farkları biliyorum. Ben sadece benim koşum blok önce çalışır çünkü benim sınama içinde yapılandırma aşamasında $ q enjekte gerekir ki bahsetmek istedim. – jbernal

+0

Cevabınız için teşekkür ederiz. Yapabildiğim kadar çabuk deneyeceğim. Bununla birlikte, daha önce test ettiğimi hatırlamak istiyorum ve işe yaramadı çünkü ikinci _beforeach_, run bloğum zaten yürütüldü ve bu nedenle, $ q undefined. – jbernal

+0

Gerçekten de işe yaramıyor. Çalıştırılan bloğumun çalıştırılması sırasında enjekte edilmesi için $ q'a ihtiyacım olabilir çünkü (beforeEach (module) ('app.core')); ') ve o anda' beforeEach (inject (function) işlevi _ $ q_) 'henüz olmadı – jbernal