2016-09-12 8 views
5

एक dagger2 मॉड्यूलएक इंजेक्शन ऑब्जेक्ट को कैसे मॉक करें जिसे मॉड्यूल में घोषित नहीं किया गया है?

@Module 
public class MyModule { 
    @Provides @Singleton public RestService provideRestService() { 
     return new RestService(); 
    } 

    @Provides @Singleton public MyPrinter provideMyPrinter() { 
     return new MyPrinter(); 
    } 
} 

हम टेस्ट के रूप में परीक्षण मॉड्यूल हो सकता था के लिए

public class TestModule extends MyModule { 
    @Override public MyPrinter provideMyPrinter() { 
     return Mockito.mock(MyPrinter.class); 
    } 

    @Override public RestService provideRestService() { 
     return Mockito.mock(RestService.class); 
    } 
} 

लेकिन अगर एक वर्ग है कि नीचे के रूप में कटार मॉड्यूल में घोषित नहीं किया गया है ... के लिए

public class MainService { 
    @Inject MyPrinter myPrinter; 

    @Inject public MainService(RestService restService) { 
     this.restService = restService; 
    } 
} 

मैं उपरोक्त के रूप में मुख्य सेवा का नकली कैसे बना सकता हूं।

नोट, मैं https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56#.9aky15kke में शेयर के अनुसार मुख्य सेवा के लिए परीक्षण करने की योजना नहीं बना रहा हूं, लेकिन इसके बजाय, मेरी मुख्य सेवा का उपयोग किसी अन्य सामान्य वर्ग में किया जाता है जिसे मैं परीक्षण करना चाहता था। जैसे

public class MyClassDoingSomething() { 
    @Inject MainService mainService; 

    public MyClassDoingSomething() { 
     //... 
    } 

    // ... 
    public void myPublicFunction() { 
     // This function uses mainService 
    } 
} 
+3

ध्यान रखें कि _unit test_ में डैगर घटकों का उपयोग करना असामान्य है क्योंकि आपके टैग इंगित करते हैं; यूनिट परीक्षण के लिए, स्वयं रचनाकारों को कॉल करें और जितनी चाहें उतने मोक्स में गुजरें। _integration_, _system_, या _end-to-end_ परीक्षण के लिए, यह वास्तविक डैगर घटक का उपयोग करने के लिए और अधिक समझ में आता है, लेकिन फिर वास्तविक परीक्षण के लिए वास्तविक निर्भरताओं का उपयोग करने के लिए यह और अधिक समझ में आता है। –

+0

धन्यवाद @ जेफबॉमन। कक्षा के नाम के कारण मैं आपको अपने इरादे से भ्रमित कर सकता हूं। मैंने MyClassDoTest को MyClassDoingSomething पर पुनर्नामित किया है। क्योंकि यह एक टेस्ट क्लास नहीं है, बल्कि एक वास्तविक वर्ग है। इसके लिए यूनिट टेस्ट एक अलग वर्ग होगा जो ऊपर दिए गए मेरे प्रश्न में परिभाषित नहीं है। घटना में मैं एक समारोह का परीक्षण कर रहा हूं i.e. MyPublicFunction MyClassDoing के भीतर कुछ जो मुख्य सेवा का उपयोग कर रहा है, मुझे एक mock mainService को MyClassDoingSomething में इंजेक्ट करने की आवश्यकता होगी। मुझे पता है कि कैसे इंजेक्ट करना है, लेकिन वास्तविक वस्तु के बजाय MyService इंजेक्ट का नकल पाने में सक्षम नहीं है। – Elye

+0

हैलो। क्या आपको अंत में एक जवाब मिला? मैं एक ही मुद्दे से अटक गया: https://stackoverflow.com/questions/45166990/mock-injected-viewmodel –

उत्तर

1

यह निश्चित रूप से अपने सवाल का जवाब नहीं है, लेकिन अपनी ईमानदार राय में यह संबंधित है, यह उपयोगी और एक टिप्पणी के लिए बहुत बड़ा है।

मुझे अक्सर इस प्रश्न का सामना करना पड़ रहा है और मैं हमेशा "कन्स्ट्रक्टर निर्भरता इंजेक्शन" कर रहा हूं।

public class MyClassDoingSomething implements DoSomethig { 
    private final Service mainService; 

    @Inject 
    public MyClassDoingSomething(Service mainService) { 
     this.mainService = mainService; 
    } 
} 

सूचना कैसे निर्माता अब पैरामीटर प्राप्त करता है और इसे करने के लिए फ़ील्ड सेट करता है और है: इसका मतलब है कि मैं अब @Inject के साथ मैदान व्याख्या द्वारा क्षेत्र इंजेक्शन है, लेकिन इतना की तरह निर्माता में निर्भरता पारित है @Inject के साथ भी एनोटेटेड? मैं भी इन वर्गों (भी MyService के लिए) एक इंटरफ़ेस को लागू करना चाहते - कई अन्य लाभ के बीच मुझे लगता है यह लिखने के लिए कटार मॉड्यूल आसान बना देता है:

@Module 
public class DoSomethingModule { 
    @Provides @Singleton public RestService provideRestService() { 
     return new RestService(); 
    } 

    @Provides @Singleton public MyPrinter provideMyPrinter() { 
     return new MyPrinter(); 
    } 

    @Provides @Singleton public Service provideMyPrinter(MyService service) { 
     return service; 
    } 

    @Provides @Singleton public DoSomethig provideMyPrinter(MyClassDoingSomething something) { 
     return something; 
    } 
} 

(मतलब यह है कि MyService औजार या Service फैली)

अब तक ऐसा लगता है कि आप पहले ही जानते हैं कि डैगर स्वयं निर्भरता ग्राफ को समझने और आपके लिए सभी ऑब्जेक्ट्स बनाने में सक्षम है। तो वर्ग MyClassDoingSomething कक्षा परीक्षण के बारे में क्या? मैं यहाँ भी डैगर का उपयोग नहीं करता हूं। मैं बस निर्भरता मैन्युअल रूप से प्रदान करता हूं:

public class MyClassDoingSomethingTest { 
    @Mock 
    Service service; 

    private MyClassDoingSomething something; 

    @Before 
    public void setUp() throws Exception { 
     MockitoAnnotations.init(this); 
     something = new MyClassDoingSomething(service); 
    } 
    // ... 
} 

जैसा कि आप देखते हैं, निर्भरता मैन्युअल रूप से निर्माता के माध्यम से पारित की जाती है।

स्पष्ट रूप से यह काम नहीं करता है अगर आप किसी ऐसे कोडिंग कर रहे हैं जिसमें आपके द्वारा कोई कन्स्ट्रक्टर नहीं है जिसे आपके द्वारा बुलाया जा सकता है। शास्त्रीय उदाहरण एंड्रॉइड गतिविधियों, टुकड़े या विचार हैं। इसे प्राप्त करने के तरीके हैं, लेकिन व्यक्तिगत रूप से मुझे अभी भी लगता है कि आप बिना किसी डैगर के इसे दूर कर सकते हैं। आप एक दृश्य एक क्षेत्र @Inject MyPresenter myPresenter है कि परीक्षण इकाई कर रहे हैं, आम तौर पर इस क्षेत्र को पैकेज का उपयोग कर सकते है कि परीक्षण में ठीक काम करता है होगा:

public class MyViewTest { 
    @Mock MyPresenter presenter; 

    private MyView view; 

    @Before 
    public void setUp() throws Exception { 
     MockitoAnnotations.init(this); 
     view.myPresenter = presenter; 
    } 
} 

ध्यान दें कि यह केवल काम करता है अगर दोनों MyViewTest और MyView एक ही पैकेज में कर रहे हैं (जो अक्सर एंड्रॉइड परियोजनाओं में मामला है)।

दिन के अंत में आप अभी भी परीक्षण के लिए चाकू का उपयोग करना चाहते हैं, तो कभी "परीक्षण" मॉड्यूल और घटक है कि जैसे घटक में तरीकों की घोषणा के द्वारा इंजेक्षन कर सकते हैं बना सकते हैं:

@Inject 
public interface MyTestComponent { 
    void inject(MyClassDoingSomething something); 
} 

मैं इस दृष्टिकोण को ठीक-एश ढूंढें, लेकिन मेरे विकास के वर्षों में मैं पहला दृष्टिकोण पसंद करता हूं। इसने Robolectric के साथ समस्याओं की सूचना दी है कि build.gradle फ़ाइल में कुछ सेटअप वास्तव में परीक्षण के लिए डैगर-कंपाइलर चलाने के लिए आवश्यक है ताकि कक्षाएं वास्तव में उत्पन्न हो जाएं।

+0

धन्यवाद फ्रेड। आपके उत्तर में, आप अभी भी मॉड्यूल में @ @ प्राइवइड @ सिंगलेटन सार्वजनिक सेवा प्रदान करते हैं MyService (MyService सेवा) 'बना रहे हैं। इसलिए यह मेरे प्रश्न को संबोधित नहीं कर रहा है। लेकिन मैं किसी अन्य दृष्टिकोण से आपके इनपुट और विस्तार की सराहना करता हूं। – Elye

+0

हाँ यह सच है। मैं यह दिखाने की कोशिश कर रहा था कि मैं परीक्षणों में मॉड्यूल का उपयोग नहीं करता, क्योंकि आप सीधे ''MyPresenter'' के निर्माता को कॉल करके निर्भरताओं का नकल कर सकते हैं। उत्पादन ऐप में आप मॉड्यूल रखेंगे। – Fred

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

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