Örnek bir uygulama geliştirdim (Evet, bu sadece bir örnek ve pek bir anlam ifade etmiyor, ancak Android temiz mimarisini ve Dagger 2'deki bağımlılık enjeksiyonunu anlamak için iyi). Benim kod github mevcuttur. Örnek uygulama sadece bir EditText
bir isim yazın ve tuşuna basınca eğer bir mesaj görüyorum "Merhaba adınız"Dagger 2 Android TestCase'de Bağımlılık Enjeksiyonu
farklı üç tane yapalım (Eski. this yayınlara bakın) Bileşenler: ApplicationComponent
, ActivityComponent
ve FragmentComponent
.
- ActivityModule
- FragmentModule
InteractorModule
bir MainInteractor
sağlar
FragmentComponent
üç modülleri içerir. Benim Etkinlik-UnitTest yılında @Module
public class InteractorModule {
@Provides
@PerFragment
MainInteractor provideMainInteractor() {
return new MainInteractor();
}
}
Ben sahte bu MainInteractor
istiyorum. Bu Interactor sadece bir Person nesnesi oluşturabilen bir public Person createPerson(String name)
metoduna sahiptir. FakeMainInteractor
aynı yönteme sahiptir, ancak her zaman geçirdiğiniz parametrenin bağımsız olarak "Sahte Kişi" ismiyle bir Kişi nesnesi oluşturur.
public class FakeMainInteractor {
public Person createPerson(final String name) {
return new Person("Fake Person");
}
}
Zaten zaten yukarıda açıklanan Bileşen I için TestComponents'ı yaratıyorum. Ve TestFragmentComponent
'da InteractorModule
'u TestInteractorModule
ile değiştirdim.
@PerFragment
@Component(dependencies = TestApplicationComponent.class, modules = {ActivityModule.class, FragmentModule.class, TestInteractorModule.class})
public interface TestFragmentComponent {
void inject(MainFragment mainFragment);
void inject(MainActivity mainActivity);
}
Bu örnek, test dışı bir bağlamda iyi çalışıyor. MainActivity
'da initializeInjector()
adlı bir yöntem var ve burada FragmentComponent
'u yapıyorum. Ve onCreate()
, 'un initializeInjector()
ve inject()
numaralarını onActivitySetup()
çağırır.
public class MainActivity extends BaseActivity implements MainFragment.OnFragmentInteractionListener,
HasComponent<FragmentComponent> {
private FragmentComponent fragmentComponent;
private Fragment currentFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
currentFragment = new MainFragment();
addFragment(R.id.fragmentContainer, currentFragment);
}
}
private void initializeInjector() {
this.fragmentComponent = DaggerFragmentComponent.builder()
.applicationComponent(getApplicationComponent())
.activityModule(getActivityModule())
.fragmentModule(getFragmentModule())
.build();
}
@Override
protected void onActivitySetup() {
this.initializeInjector();
fragmentComponent.inject(this);
}
@Override
public void onFragmentInteraction(final Uri uri) {
}
@Override public FragmentComponent getComponent() {
return fragmentComponent;
}
public FragmentModule getFragmentModule() {
return new FragmentModule(currentFragment);
}
}
Bu iyi çalışıyor. Ve benim MainActivityTest
da iyi çalışıyor. Adın yazılmasını ve aşağıdaki düğmenin sonucunu test eder. Ancak TextView
“Merhaba John” u gösterir.
public class MainActivityTest implements HasComponent<TestFragmentComponent> {
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class, true, true);
private MainActivity mActivity;
private TestFragmentComponent mTestFragmentComponent;
@Before
public void setUp() throws Exception {
mActivity = mActivityRule.getActivity();
}
@Test
public void testMainFragmentLoaded() throws Exception {
mActivity = mActivityRule.getActivity();
assertTrue(mActivity.getCurrentFragment() instanceof MainFragment);
}
@Test
public void testOnClick() throws Exception {
onView(withId(R.id.edittext)).perform(typeText("John"));
onView(withId(R.id.button)).perform(click());
onView(withId(R.id.textview_greeting)).check(matches(withText(containsString("Hello John"))));
}
@Override
public TestFragmentComponent getComponent() {
return mTestFragmentComponent;
}
}
Ama “Merhaba Sahte Kişi” yazdırmak istiyorum FakeMainInteractor
kullanmak istediğiniz söylediği gibi. Ancak, Test içindeki bağımlılık grafiğini nasıl oluşturacağımı bilmiyorum. Test modunda, orijinal Bileşenler ve Modüller yerine TestComponents ve TestModules kullanılarak başka bir grafik oluşturulmasını istiyorum. Peki bunu nasıl yapmalı? Testin FakeMainInteractor
nasıl kullanılmasına izin verilir?
Söylediğim gibi, bu örnek uygulamanın yararlı bir şey yapmadığını biliyorum. Ama Hançer 2 ile Testi anlamak istiyorum. Zaten this makalesini okudum. Ama sadece TestComponents ve TestModules nasıl yapılır gösterir. Birim Testinde bir Test-Grafiğinin nasıl kullanılacağını anlatmaz. Bu nasıl yapılır? Birisi bir örnek kod sağlayabilir mi? Kullandığı ve Hançer 2 (ı sürüm 2.7 kullanmak) eski sürümü ve TestComponents lantÛlarÛyla açıklanmaz yapar çünkü
This, benim için bir çözüm değildir.
@Override
public void setFragmentComponent(final FragmentComponent fragmentComponent) {
Log.w(TAG, "Only call this method to swap test doubles");
this.fragmentComponent = fragmentComponent;
}
AndroidApplication
sahibi:
public void setApplicationComponent(ApplicationComponent applicationComponent) {
Log.w(TAG, "Only call this method to swap test doubles");
this.applicationComponent = applicationComponent;
}
Hançer test için kullanılmaz. İlk olarak, sınıflarınızı, sınıfları bağımlılıkların sahte/alaylarıyla test etmeyi kolaylaştıracak iyi yan etkiye sahip olan DI'yi kullanacak şekilde mimarlık yapmak zorundasınız. bağımlılıkları manuel olarak veya alaycı bir çerçeve kullanarak yenileyebilirsiniz. – Nkosi
Mimarim zaten DI için hazır. Mimariyi test vakasına uygulayamıyorum. Tam olarak "bağımlılıkları el ile yeni" ile ne demek istiyorsun? – unlimited101
, "FakeMainInteractor" ın yeni bir örneğini oluşturup, bunu başlatırken sınanacak sisteme enjekte edersiniz. Ayrıca sahte ve somut uygulamalarınız ortak bir soyutlamayı paylaşmalıdır. – Nkosi