2016-11-05 7 views
5

मैं एक Presenter वर्ग है जो एक क्षेत्र डैगर के माध्यम से इंजेक्शन का उपयोग करता है, यह इस तरह दिखता है:इकाई में एक इंजेक्शन क्षेत्र मजाक परीक्षण

public class RssListPresenter { 

    @Inject 
    RssService rssService; // <-- injected field 

    public RssListPresenter() { 
     setupDI(); 
    } 

    private void setupDI() { 
     DaggerNetworkComponent.builder() 
       .networkModule(new NetworkModule()) 
       .build() 
       .inject(this); 
    } 

    public void loadItems() { 
     Rss rss = rssService.getRssFeed() 
     // .... 
    } 
} 

सब कुछ ठीक काम करता है। अब, मैं इकाई को RssListPresenter कक्षा का परीक्षण करना चाहता हूं। प्रश्न यह है कि मैं प्रस्तुतकर्ता को नकली RssService कैसे प्रदान करूं?

संभोग मैं प्रस्तुतकर्ता को setRssService(RssService rssService) जोड़ सकता हूं और यूनिट परीक्षणों से नकली प्रदान करने के लिए इसका उपयोग कर सकता हूं, लेकिन यूनिट परीक्षणों के लिए यह विधि जोड़ना सही नहीं लगता है। इसे संभालने का सही तरीका क्या होगा?

पूर्णता के लिए यहां मॉड्यूल और घटक घोषणाओं हैं: जैसे कि परीक्षण करने के लिए इतना आसान नहीं है

@Singleton 
@Component(modules = NetworkModule.class) 
public interface NetworkComponent { 
    void inject(RssListPresenter presenter); 
} 

@Module 
public class NetworkModule { 

    @Provides 
    Retrofit provideRetrofit() { 
     // ... 
    } 

    @Provides 
    @Singleton 
    RssService providePcWorldRssService(Retrofit retrofit) { 
     return retrofit.create(RssService.class); 
    } 

} 
+0

एक बार के लिए: जब आपके पास यूनिट टेस्ट नहीं है तब तक आप कैसे जानते हैं कि यह ठीक काम करता है? और दूसरा: फ़ील्ड न तो 'निजी' और न ही 'अंतिम' है, इसलिए आप इसे अपने टेस्ट क्लास से सेट कर सकते हैं (यदि यह एक ही पैकेज में है)। –

+0

1 - आप ऐप चलाते हैं, और जब फ़ील्ड इंजेक्शन नहीं होता है तो आप तुरंत परिणाम देखते हैं :), 2 - मुझे लगता है कि मैं नीचे दिए गए अनुसार इंजेक्शन इंजेक्शन के साथ जाऊंगा, लेकिन आपके सुझावों के लिए भी धन्यवाद। –

+0

* "और जब क्षेत्र इंजेक्शन नहीं दिया जाता है तो आप तुरंत परिणाम देखते हैं :)" * ठीक है, लेकिन वह "डी फ्रैमवर्क काम करता है" और यह मेरी समझ नहीं है कि "सब ठीक काम करता है" जिसमें वास्तविक व्यवहार शामिल है * मेरे * कोड, किसी भी ढांचे का कोड नहीं। यही कारण है कि मैंने पूछा ...; ओ) –

उत्तर

5

संपत्ति इंजेक्शन है। इस मामले में, कन्स्ट्रक्टर इंजेक्शन बहुत बेहतर है। इस तरह देखने के लिए अपने निर्माता refactor:

private final RssService rssService; 

@Inject 
public RssListPresenter(RssService rssService) { 
     this.rssService = rssService; 
} 

अब आप इसे आसानी से परीक्षण कर सकते हैं:

//mocks 
RssService mockRssService; 

//system under test 
RssListPresenter rssListPresenter; 

@Before 
public void setup() { 
    mockRssService = Mockito.mock(RssService.class); 
    rssListPresenter = new RssListPresenter(mockRssService); 
} 

आप शायद RssListPresenter अंदर DaggerNetworkComponent.inject(this) नहीं का उपयोग करना चाहिए। इसके बजाय आपको डैगर को कॉन्फ़िगर करना चाहिए ताकि जब यह आपके शीर्ष-स्तरीय कक्षाओं (Activity, Fragment, Service) में सदस्यों को इंजेक्ट करे, तो यह ऑब्जेक्ट ग्राफ़ तक पहुंच सकता है और आपके RssPresenter का उदाहरण बना सकता है।

क्यों केवल Activity और Service में इंजेक्टर डालें और RssListPresenter जैसे कुछ में नहीं? ये कक्षाएं हैं जिन्हें एंड्रॉइड सिस्टम द्वारा तत्काल किया जाता है और इसलिए आपके पास इंजेक्टरों का उपयोग करने के अलावा कोई विकल्प नहीं है।

स्पष्टीकरण के लिए, Activity, Fragment आदि आदर्श इंजेक्शन लक्ष्य हैं। RssListPresenter आदि इंजेक्शन निर्भरता हैं। आपको निर्भरता इंजेक्शन फ्रेमवर्क, डैगर को कॉन्फ़िगर करने की आवश्यकता है, ताकि यह इंजेक्शन लक्ष्यों में इंजेक्ट करने के लिए सही निर्भरता प्रदान कर सके।

तो तुम भी के लिए RssListPresenter

@Provides provideRssListPresenter(RssService rssService) { 
    return new RssListPresenteR(rssService); 
} 
+0

विस्तृत स्पष्टीकरण और उदाहरण के लिए धन्यवाद! –

+0

क्या होगा यदि वह एक और कन्स्ट्रक्टर जोड़ता है जो केवल परीक्षण उद्देश्यों के लिए 'रुपये सेवा 'पैरामीटर लेता है? –

+1

@ निकोलाडेस्पोटोसकी सुनिश्चित नहीं है कि आप ऐसा क्यों करना चाहते हैं। आप अपनी कक्षाओं को डिजाइन करना चाहते हैं ताकि वे साफ हो जाएं और उन्हें केवल परीक्षण के लिए बदलने की ज़रूरत नहीं है, है ना? –

0

आपका वर्ग S.O.L.I.D सिद्धांतों में से कुछ का उल्लंघन करती है एक @Provides विधि लिखने के लिए की आवश्यकता होगी, और यह यह बहुत इकाई परीक्षण यह करने के लिए कठिन बना देता है। निश्चित रूप से आपकी कक्षा एसआरपी (एकल उत्तरदायित्व सिद्धांत) का उल्लंघन करती है क्योंकि इसमें एक से अधिक बदलने का कारण है। एक संभावित निर्भरता उलटा उल्लंघन भी है।

मैं कक्षाओं के मॉडल पर पुनर्विचार करने की सलाह देता हूं, ताकि उनमें से प्रत्येक एक विशिष्ट कार्य करता है, और इसमें बदलने का एक कारण है।

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