2011-06-24 12 views
20

मुझे यह जांचने की कोशिश में कुछ रोचक विपत्तियां थीं कि विचार घटनाओं के लिए सही तरीके से बंधे थे या नहीं। रीढ़ की हड्डी में, हम आमतौर पर प्रारंभिक विधि में घटनाओं से जुड़ते हैं, something.bind("change", this.render); की रेखाओं के साथ कुछ का उपयोग करते हैं। मेरे परीक्षण में, मैं यह सुनिश्चित करना चाहता हूं कि यह बाध्यकारी स्थापित हो गया है, इसलिए मैंने निम्न कार्य किया:जैस्मीन के साथ backbone.js अनुप्रयोग का परीक्षण - एक दृश्य पर मॉडल बाइंडिंग का परीक्षण कैसे करें?

this.myView = new MyView(); 
spyOn(this.myView, "render");; 
this.legendView.groupData.trigger("change"); 
expect(this.legendView.render).toHaveBeenCalled(); 

लेकिन, यह काम नहीं करेगा। चूंकि बाइंड MyView के प्रारंभिक फ़ंक्शन में होता है, इसलिए ईवेंट उस समय मेरे व्यू के प्रस्तुत करने के लिए बाध्य हो जाता है। इसलिए, जब आप अपना जासूस जोड़ते हैं, तो यह रेंडर फ़ंक्शन को लपेटता है और इसे वापस मेरेView.render पर सेट करता है। लेकिन पहले बांध से निर्मित बंद अभी भी मौजूद है, और हम पूरी तरह से होज कर रहे हैं। तो इसके बारे में हमारे द्वारा क्या किया जा सकता है?

myView = Backbone.View.extend({ 
initialize: function(){ 
    _.bindAll(this, "render"); 
    this.initialize_model_bindings(); 
}, 
initialize_model_bindings: function(){ 
    something.bind("change", this.render); 
}, 
render: function(){ //... } 
}); 

और अपने परीक्षण तो लगता है कि:: मैं क्या किया था, को स्थानांतरित मेरी बाँध कॉल की एक अलग कार्य करने के लिए, कुछ की तरह है

this.myView = new MyView(); 
spyOn(this.myView, "render"); 
this.myView.initialize_model_bindings(); 
this.legendView.groupData.trigger("change"); 
expect(this.legendView.render).toHaveBeenCalled(); 

यह काम करता है, लेकिन मैं एक बेहतर समाधान के लिए देख रहा हूँ । धन्यवाद

+0

क्या आप इस बिंदु को समझाते हैं "लेकिन पहले बांध से बनाए गए बंद अभी भी मौजूद हैं, और हम पूरी तरह से फिर से हो गए हैं"? मुझे एक ही समस्या है और यह समझने की कोशिश कर रहा है कि क्या हो रहा है। धन्यवाद। –

+1

जब आप 'नया MyView() 'कहते हैं, प्रारंभिक विधि को कॉल किया जाता है, और उस समय ऑब्जेक्ट में मौजूद फ़ेंडर फ़ंक्शन परिवर्तन ईवेंट से जुड़ा होता है। उस बिंदु से, रेंडर फ़ंक्शन तक पहुंचना असंभव है जो परिवर्तन ईवेंट से जुड़ा हुआ है - यह बंद होने में बंद है। स्पष्टीकरण के लिए – idbentley

+0

धन्यवाद। –

उत्तर

5

कॉलबैक पर जासूसी करने के बजाय आप किसी चीज़ पर जासूसी करने का प्रयास कर सकते हैं। फिर परीक्षण करें कि बांध को उचित तर्क कहा जाता है। यह अब तक मेरे लिए काम कर रहा है। मैं जैस्मीन के अंतर्निहित जासूसों के बजाय sinon.js का उपयोग कर रहा हूँ। sinon.js उसी विधि कॉल के ढेर में एक विधि कॉल में पास किए गए तर्कों के लिए परीक्षण करना थोड़ा आसान बनाता है (उदाहरण के लिए एक दृश्य init में बाध्य करने के लिए कॉल का एक गुच्छा)। तो मैंने अकेले इस विचार w/jasmine का परीक्षण नहीं किया है लेकिन मानना ​​है कि यह संभव होना चाहिए।

spyOn(this.legendView.groupData, 'bind'); 
this.myView = new MyView(); 
expect(this.legendView.groupData.mostRecentCall.args).toEqual('change', this.myView.render); // example!! only works if testing a single call to bind or the last call in a series (ie mostRecentCall) 

और डब्ल्यू/sinon.js

sinon.spy(this.legendView.groupData, 'bind'); 
this.myView = new MyView(); 
expect(this.legendView.groupData.bind.calledWith('change', this.myView.render); // works w/ any number of calls to bind 
3

मैं एक समारोह मेरी समारोह प्रस्तुत करना द्वारा कहा जाता है पर जासूसी इस समस्या का समाधान। अपने उदाहरण में तो:

myView = Backbone.View.extend({ 
    initialize: function(){ 
     _.bindAll(this, "render"); 
     something.bind("change", this.render); 
    }, 
    someOtherFunction: function(){}, //this function only called from render 
    render: function(){ this.someOtherFunction(); /* rest of render function */ } 
}); 

परीक्षण लगता है:

this.myView = new MyView(); 
spyOn(this.myView, "someOtherFunction"); 
this.myView.something.trigger("change"); 
expect(this.myView.someOtherFunction).toHaveBeenCalled(); 

तो मैं एक अलग परीक्षण जो कुछ के लिए someOtherFunction करता है लिखा था।

+0

यह एक भयानक समाधान की तरह प्रतीत नहीं होता है, लेकिन मुझे लगता है कि मेरे प्रस्तुत कार्यों में अक्सर परिवर्तन होता है। मुझे लगता है कि अगर मैंने ऐसा किया तो मैं अपने चश्मे को काफी अद्यतन कर रहा हूं। – idbentley

2

आपको Sinon.js को देखने पर विचार करना चाहिए। आप रेंडर() कॉल को स्टब/मॉक कर सकते हैं और 'someOtherFunction()' के बारे में चिंता करने की भी आवश्यकता नहीं है।

1

यह भी बारीकी से रीढ़ internals के साथ मिलकर किया जा सकता है, लेकिन आप मैन्युअल रूप से कॉलबैक श्रृंखला की जाँच कर सकते हैं:

expect(this.legendView.groupData._callbacks['change']).toContain(this.myView.render) 
12

मैं इस का उपयोग कर प्रोटोटाइप पैचिंग को प्राप्त करने में कामयाब रहे है। दृश्य का उदाहरण बनाने से पहले, spyOn निर्माता का प्रोटोटाइप।

spyOn(MyView.prototype, 'changeSelected'); 
var view = new MyView(); 
view.selectSomething(); 
expect(view.changeSelected).toHaveBeenCalled(); 
+0

किसी कारण से यह मेरे लिए केवल 'sinon.spy (...) 'का उपयोग कर रहा है। इस संकेत के लिए धन्यवाद! – fifigyuri

+0

अगर मुझे पिछले साल में साइनऑन की एपीआई बदल गई है तो मुझे आश्चर्य नहीं होगा ... – mjtamlyn

0

मैं एक ही समस्या में पड़ गए और से मेरा विचार बदल कोड:

this.model.on('change', this.render, this); 

रहे हैं:

this.model.on('change', function() { 
    this.render(); 
}, this); 

और मेरे चमेली परीक्षण काम अपेक्षा के अनुरूप।

संबंधित मुद्दे