2012-01-04 24 views
57

Aşağıdaki yöntemin Javascript nesne yapıcımda olup olmadığını test etmek istiyorum. Jasmine belgelerinde gördüklerimden, bir yapıcı yöntem üzerinde casusluk yapabilirim ve bir nesne oluşturulduktan sonra yöntemler üzerinde casusluk yapabilirim, ancak nesne oluşturulmadan önce bir yöntem üzerinde casusluk edemiyorum. Jasmine - Bir kurucu içinde bir yöntem çağrısında casusluk yapma

nesne:

it('should spy on a method call within the constructor', function() { 
    spyOn(window, 'Klass'); 
    var obj = new Klass(); 
    expect(window.Klass.called_method).toHaveBeenCalled(); 
}); 

cevap

98

Casus doğrudan prototip yöntemine:

describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
     spyOn(Klass.prototype, 'called_method'); //.andCallThrough(); 
     var k = new Klass(); 
     expect(Klass.prototype.called_method).toHaveBeenCalled(); 
    }); 
}); 
+3

bunun için teşekkürler. En iyi açıklama konuyla ilgili bütün günü gördüm – Subimage

+0

Bir önsezide bunun için meşru bir çözüm vardı. Teşekkür ederim. – BradGreens

+0

Bu yaklaşımla ilgili iki sorun var. Birincisi, bir bellek sızıntısına neden oluyor - Klass'ın gelecekteki tüm örnekleri çağrıldı ve daha fazla çağrı yapıldıktan sonra casusun bellek tüketimi artacak. İkincisi ve daha da önemlisi, bu da potansiyel olarak, Klass'ın daha önce çağrıldığından, Klass'ı birbiriyle etkileşimde bulunacak şekilde sorgulayan birden fazla teste neden olur. Casusun silinmiş olduğundan emin olmalısınız veya Klass.prototype.called_method test vakasının sonunda orijinal yönteme sıfırlanmalıdır. – alecmce

11

Geniş, kabul ediyorum

Klass = function() { 
    this.called_method(); 
}; 

Klass.prototype.called_method = function() { 
    //method to be called in the constructor. 
} 

Spec böyle bir şey yapmak istiyorum Yukarıdaki Dave Newton'un cevabı ile. Bununla birlikte, düşünmeniz gereken bu yaklaşımın bazı kenar durumları vardır.

başka bir test-dava ile, Dave'in çözümüne bir varyasyon atın: İlk testte casus kurulum ikinci yöntem haline testi sınırlarının ötesinde devam çünkü

// production code 
var Klass = function() { 
    this.call_count = 0; 
    this.called_method(); 
}; 
Klass.prototype.called_method = function() { 
    ++this.call_count; 
}; 

// test code 
describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
    spyOn(Klass.prototype, 'called_method'); 
    var k = new Klass(); 
    expect(k.called_method).toHaveBeenCalled(); 
    }); 
    it('some other test', function() { 
    var k = new Klass(); 
    expect(k.call_count).toEqual(1); 
    }); 
}); 

ikinci test başarısız olur; called_method call_count değerini artırmaz, bu yüzden this.call_count 1'e eşit değildir. Ayrıca yanlış pozitiflerle senaryolar oluşturmak da mümkündür.

Bunun üzerine, casus kaldığı için, oluşturulan Klass örnekleri ne kadar büyük olursa, casuslar bellek casusunu ne kadar büyük tüketir, çünkü casus her çağrıyı call_method'a kaydeder. Muhtemelen çoğu durumda bir sorun değildir, ancak her durumda bunun farkında olmalısınız.

Bu sorunun basit bir çözümü, casusun kullanımdan sonra kaldırıldığından emin olmaktır. Bu biraz çirkin bakabilirsiniz, ama böyle bir şey çalışır:

// test code 
describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
    var spy = jasmine.createSpy('called_method'); 
    var method = Klass.prototype.called_method; 
    Klass.prototype.called_method = spy; 
    var k = new Klass(); 
    expect(spy).toHaveBeenCalled(); 
    Klass.prototype.called_method = method; 
    }); 

[NOT - Küçük bir görüş bitirmek için] Daha iyi bir çözüm, üretim kodu test etmek kod kolaylaştırmak için yazma biçimini değiştirmek olacaktır. Kural olarak, prototip üzerinde casusluk yapmak, kaçınılması gereken bir kod-kokudur. Yapıcıya bağımlılıkları ortaya koymak yerine, bunları enjekte edin. Kurucuda başlatma yapmak yerine, uygun bir init yöntemini ertele.

+1

+1, ek bilgi için teşekkürler. Bence "NOT" bölümünün hemen hemen herşeyi özetliyor; Testten ziyade başka bir yerde düzeltilmesi gerektiği kesin. –

+0

Bu, Jasmine'in son sürümleriyle çalışır. –

+0

Evet, sanırım bunu bir süre önce kapatmışlar. İlke olarak prototip üzerinde casusluktan kaçınmaya değer. – alecmce