Saya baru saja mulai bermain dengan Guice, dan kasus penggunaan yang dapat saya pikirkan adalah bahwa dalam ujian saya hanya ingin mengganti satu pengikatan. Saya pikir saya ingin menggunakan sisa ikatan tingkat produksi untuk memastikan semuanya sudah diatur dengan benar dan untuk menghindari duplikasi.
Jadi bayangkan saya memiliki Modul berikut
public class ProductionModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(ConcreteA.class);
binder.bind(InterfaceB.class).to(ConcreteB.class);
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
}
Dan dalam pengujian saya, saya hanya ingin mengesampingkan InterfaceC, sambil tetap menjaga InterfaceA dan InterfaceB, jadi saya ingin sesuatu seperti:
Module testModule = new Module() {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(new ProductionModule(), testModule);
Saya juga sudah mencoba yang berikut ini, tanpa hasil:
Module testModule = new ProductionModule() {
public void configure(Binder binder) {
super.configure(binder);
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(testModule);
Adakah yang tahu apakah itu mungkin untuk melakukan apa yang saya inginkan atau saya benar-benar menggonggong pohon yang salah ??
--- Tindak lanjut: Tampaknya saya dapat mencapai apa yang saya inginkan jika saya menggunakan tag @ImplementedBy pada antarmuka dan kemudian hanya memberikan pengikatan dalam test case, yang berfungsi dengan baik ketika ada 1-1 pemetaan antara antarmuka dan implementasi.
Juga, setelah mendiskusikan hal ini dengan seorang kolega, sepertinya kita akan menuju jalan menimpa seluruh modul dan memastikan kita memiliki modul kita didefinisikan dengan benar. Hal ini sepertinya dapat menyebabkan masalah meskipun di mana pengikatan salah tempat dalam modul dan perlu dipindahkan, sehingga mungkin memecah beban tes karena binding mungkin tidak lagi tersedia untuk diganti.
sumber
Jawaban:
Ini mungkin bukan jawaban yang Anda cari, tetapi jika Anda menulis tes unit, Anda mungkin tidak harus menggunakan injektor dan lebih baik menyuntikkan tiruan atau benda palsu dengan tangan.
Di sisi lain, jika Anda benar-benar ingin mengganti satu ikatan, Anda dapat menggunakan
Modules.override(..)
:Lihat detailnya di sini .
Tetapi sebagai javadoc untuk
Modules.overrides(..)
merekomendasikan, Anda harus mendesain modul Anda sedemikian rupa sehingga Anda tidak perlu menimpa binding. Dalam contoh yang Anda berikan, Anda bisa mencapainya dengan memindahkan pengikatanInterfaceC
ke modul terpisah.sumber
ovveride
kehilangan yang tepatStage
saat melakukannya (yaitu PEMBANGUNAN digunakan secara sistematis).Mengapa tidak menggunakan warisan? Anda dapat mengganti ikatan spesifik Anda dalam
overrideMe
metode, meninggalkan implementasi bersama dalamconfigure
metode.Dan akhirnya buat injektor Anda dengan cara ini:
sumber
@Override
tampaknya tidak bekerja. Apalagi jika itu dilakukan pada metode@Provides
sesuatu itu.Jika Anda tidak ingin mengubah modul produksi Anda dan jika Anda memiliki struktur proyek suka-suka standar seperti
Anda bisa membuat kelas baru
ConcreteC
di direktori tes Anda menggunakan paket yang sama dengan kelas asli Anda. Guice maka akan mengikatInterfaceC
keConcreteC
dari direktori tes sedangkan semua antarmuka lain akan terikat untuk kelas produksi Anda.sumber
Anda ingin menggunakan Juckito di mana Anda dapat mendeklarasikan konfigurasi khusus Anda untuk setiap kelas uji.
sumber
Dalam pengaturan yang berbeda, kami memiliki lebih dari satu aktivitas yang didefinisikan dalam modul terpisah. Aktivitas yang disuntikkan ke dalam Modul Perpustakaan Android, dengan definisi modul RoboGuice sendiri dalam file AndroidManifest.xml.
Setup terlihat seperti ini. Dalam Modul Perpustakaan ada definisi ini:
AndroidManifest.xml:
Kemudian kami memiliki jenis yang disuntikkan:
Beberapa implementasi standar Foo:
MainModule mengkonfigurasi implementasi FooThing untuk Foo:
Dan akhirnya, Aktivitas yang mengonsumsi Foo:
Dalam Modul Aplikasi Android yang mengkonsumsi, kami ingin menggunakan
SomeActivity
tetapi, untuk tujuan pengujian, menyuntikkan kami sendiriFoo
.Orang mungkin berpendapat untuk mengekspos modul penanganan aplikasi klien, namun, kita perlu menyembunyikan sebagian besar komponen yang disuntikkan karena Modul Perpustakaan adalah SDK, dan mengekspos potongan memiliki implikasi yang lebih besar.
(Ingat, ini untuk pengujian, jadi kami tahu bagian dalam SomeActivity, dan tahu itu menghabiskan (paket terlihat) Foo).
Cara saya menemukan bahwa bekerja itu masuk akal; gunakan penggantian yang disarankan untuk pengujian :
Sekarang, ketika
SomeActivity
dimulai, ia akan mendapatkanOtherFooThing
untukFoo
contoh yang disuntikkan .Ini adalah situasi yang sangat spesifik di mana, dalam kasus kami, OtherFooThing digunakan secara internal untuk merekam situasi pengujian, sementara FooThing digunakan, secara default, untuk semua penggunaan lainnya.
Perlu diingat, kita sedang menggunakan
#newDefaultRoboModule
dalam tes unit kami, dan bekerja sempurna.sumber