2017-03-29 10 views
5

के लिए एक डैगर 2 इंजेक्शन निर्भरता का मज़ाक उड़ा रहा है। मेरे पास भारी निर्भरता इंजेक्शन (डैगर 2) एप्लिकेशन है। मैं पूरे आवेदन के माध्यम से परीक्षण नेविगेट किए बिना, एस्प्रेसो परीक्षण चलाने के लिए, और एप्लिकेशन में लॉग इन करना चाहता हूं।एंड्रॉइड एक एस्प्रेसो परीक्षण

मैं अपनी टेलीएक्टिविटी शुरू करना चाहता हूं, और लॉगिन प्रबंधक का मज़ाक उड़ाऊंगा। हालांकि किसी भी @ टेस्ट फ़ंक्शन में, हमने पहले से ही शून्य सूचक को मारा है क्योंकि हमने क्रेट को बुलाया है। अगर हम गतिविधि लॉन्च करने से पहले इसे ओवरराइड करते हैं (नीचे दिखाएं) गतिविधि शून्य है।

मेरी समझ के लिए, हमारी रेखांकित निर्भरताओं को स्विच करने की क्षमता एक बड़ा कारण है कि हम डैगर 2 का उपयोग क्यों करते हैं, अन्यथा यह केवल एक बहुत अधिक इंजीनियर सिंगलटन होगा। मैं एक परीक्षण डैगर मॉड्यूल में इंजेक्शन को ओवरराइड, नकली या स्विच कैसे करूं - इसलिए मैं यह सरल एस्प्रेसो परीक्षण बना सकता हूं।

नोट मैंने एमवीपी डिज़ाइन पैटर्न में यह सब भी लिखा है यदि इससे कोई फर्क पड़ता है।

TeleActivity

@Inject 
TelePresenter mTelePresenter; 
@Inject 
public LoginStateManager mLoginStateManager; 

    @Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ButterKnife.bind(this); 
    DaggerInjectorTele.get().inject(this); 
    mTelePresenter.setTeleDependencies(this); 
    Intent intent = getIntent(); 

    String searchId = null; 

    if (intent != null) { 
     searchId = intent.getStringExtra(Constants.SEARCH_ID); 
     } 

    mTelePresenter.onCreateEvent(searchId, 
      Helper.makeAuthorizationHeader(
      // CRASH Null pointer 
      mLoginStateManager.getBaseLoginResponse().getAccessToken())); 

} 

एस्प्रेसो

@LargeTest 
@RunWith(AndroidJUnit4.class) 
public class TeleTest { 
    @Rule 
    public ActivityTestRule<TeleActivity> mActivityTestRule = new ActivityTestRule(
      TeleActivity.class) { 
     @Override 
     protected void beforeActivityLaunched() { 
      super.beforeActivityLaunched(); 
      TeleActivity teleActivity = (TeleActivity)getActivity(); 
      //teleActivity NULL! 
      teleActivity.mLoginStateManager = mock(LoginStateManager.class); 
      LoginResponse loginResponse = mock(LoginResponse.class); 
      when(loginResponse.getAccessToken()).thenReturn("1234"); 
      // Nope here still null 


when(teleActivity.mLoginStateManager.getBaseLoginResponse()).thenReturn(loginResponse); 

     } 
    }; 

डैगर इंजेक्टर

public class DaggerInjectorTele { 
    private static TelePresenterComponent telePresenterComponent = 
      DaggerTelePresenterComponent.builder().build(); 

    public static TelePresenterComponent get() { 
     return telePresenterComponent; 
    } 
} 

TelePresenterComponent

@Singleton 
@Component(modules = {TelePresenterModule.class, 
     LoginStateManagerModule.class}) 
public interface TelePresenterComponent { 
    void inject(TeleActivity activity); 
} 

TelePresenterModule

@Module 
public class TelePresenterModule { 

    @Provides 
    @Singleton 
    public TelePresenter getTelePresenter() { 
     return new TelePresenter(); 
    } 
} 

LoginStateManagerModule

@Module 
public class LoginStateManagerModule { 

    @Provides 
    @Singleton 
    public LoginStateManager getLoginStateManager(){ 
     return new LoginStateManager(); 
    } 
} 

उत्तर

5

पहले निर्धारित करने की आवश्यकता) एक बहुत अच्छा है और वास्तव में आपके परीक्षणों को लिखना आसान बना देगा।

आपको निर्भरता इंजेक्शन कॉन्फ़िगरेशन (मॉड्यूल) को ओवरराइड करना होगा और एक नकली इंजेक्ट करना होगा। यहां एक सरल उदाहरण दिया गया है कि यह कैसे किया जा सकता है।

सबसे पहले आप एक नकली की जरूरत है:

LoginStateManager lsmMock = mock(LoginStateManager.class); 

अब उपयोग करने के लिए डि config ओवरराइड इस नकली:

//Extend your TelePresenterModule, override provider method 
public class TestTelePresenterModule extends TelePresenterModule{ 
    @Override 
    public LoginStateManager getLoginStateManager() { 
     //simply return the mock here 
     return lsmMock; 
    } 
} 

अब परीक्षण के लिए:

@Test 
//this is an espresso test 
public void withAMock() { 
    //build a new Dagger2 component using the test override 
    TelePresenterComponent componentWithOverride = DaggerTelePresenterComponent.builder() 
      //mind the Test in the class name, see a class above 
      .telePresenterModule(new TestTelePresenterModule()) 
      .build(); 

    //now we initialize the dependency injector with this new config 
    DaggerInjectorTele.set(componentWithOverride); 

    mActivityRule.launchActivity(null); 

    //verify that injected mock was interacted with 
    verify(lsmMock).whatever(); 
} 

उदाहरण से: https://github.com/yuriykulikov/DIComparison/blob/master/app/src/androidTest/java/com/example/yuriy/dependencyinjectioncomparison/Dagger2Test.java

+0

मैं बहुत करीब था! मैंने देखा अन्य उदाहरण इंजेक्टर को ओवरराइड नहीं किया था। मैंने एक और चीज की, जिसे मैं अपने प्रश्न के तहत पोस्ट करूंगा। – StarWind0

0

वास्तुकला समस्या के बजाय एक छोटी समस्या की तरह लगता है।

सबसे पहले मैं डैगर 2 घटक को कॉल करने के लिए एक स्थिर वर्ग नहीं बनाउंगा, मेरा दृष्टिकोण अधिक एंड्रॉइड केंद्रित होगा, मेरा मतलब है कि सिंगलटन एप्लिकेशन का उपयोग अपनी सभी घंटियों और सीटी के साथ करना है।

1- यूआई अनुप्रयोग, अपने Android गतिविधियों और टुकड़े, आदि ...

:

वैसे भी ... पूरा काम प्रवाह चलने के बिना परीक्षण चलाने के लिए सबसे अच्छा तरीका है दो अलग अलग परियोजनाओं में अपनी परियोजना को अलग करने के लिए है

2-तर्क एक उद्यम संरचना का उपयोग कर मॉड्यूल कहना एमवीपी/MVC/MVVM

आप कटार कहाँ का उपयोग करना चाहिए (यह अपने Android स्टूडियो के अंदर एक अलग परियोजना होना चाहिए)? अपने यूआई में तर्क मॉड्यूल चिपकाने के लिए अपने यूआई ऐप के अंदर।

आप ऐप के विभिन्न भाग (तर्क मॉड्यूल) का परीक्षण कैसे कर सकते हैं? चूंकि आपने अपने तर्क को अलग-अलग हिस्सों में अलग-अलग हिस्सों में अलग कर दिया है, इसलिए उनके लिए एस्पेरसो की आवश्यकता नहीं होगी, भले ही आप कहीं अधिक आसान हों। जुनीट और मॉकिटो के साथ सरल यूनिट परीक्षण पूरे काम-प्रवाह को चलाने के बिना आपकी मदद कर सकता है।

ध्यान दें कि आपके यूआई ऐप के अंदर आपके पास कोई तर्क नहीं होना चाहिए।

मेरे राय साफ वास्तुकला है: https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

मैं तुम्हें वह भी पढ़ सकते हैं मेरी GitHub में ऊपर दृष्टिकोण के लिए एक सरल पाड़ है, अच्छी तरह से करता है, तो आप कल्पना: https://github.com/vahidhashemi/android_clean_architecture

+0

हाय महिद, जवाब के लिए धन्यवाद। हालांकि मुझे डर है कि मेरा सवाल नहीं था, यूनिट परीक्षणों के लिए सबसे अच्छा आर्किटेक्चर क्या है। एस्प्रेसो परीक्षण के लिए नकली कैसे है। मुझे लगता है कि आप कैसे सुझाव देते हैं कि मैं एमवीपी करता हूं, क्योंकि मेरे प्रश्न में राज्य था कि हम एमवीपी आर्किटेक्चर का उपयोग करते हैं। आपके द्वारा सुझाए गए परिवर्तनों के साथ भी, मुझे डर है कि हमें अभी भी एक ही समस्या है। अब मुझे इंजेक्शन सिंगलटन के बजाय सिंगलटन की नकल करने की ज़रूरत है। – StarWind0

0

कोई

में सेट मूल्य है

LoginStateManager

तो whe n आप उस घटक का निर्माण करते हैं जो आपको टेलीपेंडरर निर्भरता और लॉगिनस्टेट प्रबंधक निर्भरता लेकिन दोनों के सदस्य चर में कोई मान सेट नहीं है। इसलिए मुझे लगता है कि उन्हें एक्सेस करने से पहले सदस्य चर के मान सेट करने की आवश्यकता है।

getBaseLoginResponse().getAccessToken()) 

कोड के ऊपर लाइन आप अशक्त क्योंकि आप इसे एक्सेस करने से पहले मूल्य तो सेट नहीं किया है दे रहा है आप, निर्भरता इंजेक्शन का उपयोग करने के अपने निर्णय (Dagger2 मूल्यों पहले

+0

हाय नवनीत। समूह में आपका स्वागत है। मैं प्रश्नों को बहुत सावधानीपूर्वक पढ़ने की सलाह दूंगा। आप देखेंगे कि यह एक एस्प्रेसो, डैगर 2 है, मॉकिंग सवाल है। यदि आप इन विषयों से परिचित नहीं हैं, तो आप जवाब देने में सक्षम नहीं होंगे। तथ्य यह है कि प्रबंधक सेट नहीं है, वास्तव में वह मुद्दा है जिसे हम हल करने की कोशिश कर रहे हैं। सवाल यह है कि इस माहौल में इन मूल्यों को कैसे सेट किया जाए। – StarWind0

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