Dengan asumsi antarmuka IReader, implementasi antarmukaIeader ReaderImplementation, dan kelas ReaderConsumer yang mengkonsumsi dan memproses data dari pembaca.
public interface IReader
{
object Read()
}
Penerapan
public class ReaderImplementation
{
...
public object Read()
{
...
}
}
Konsumen:
public class ReaderConsumer()
{
public string location
// constructor
public ReaderConsumer()
{
...
}
// read some data
public object ReadData()
{
IReader reader = new ReaderImplementation(this.location)
data = reader.Read()
...
return processedData
}
}
Untuk menguji ReaderConsumer dan pemrosesan saya menggunakan tiruan dari IReader. Jadi ReaderConsumer menjadi:
public class ReaderConsumer()
{
private IReader reader = null
public string location
// constructor
public ReaderConsumer()
{
...
}
// mock constructor
public ReaderConsumer(IReader reader)
{
this.reader = reader
}
// read some data
public object ReadData()
{
try
{
if(this.reader == null)
{
this.reader = new ReaderImplementation(this.location)
}
data = reader.Read()
...
return processedData
}
finally
{
this.reader = null
}
}
}
Dalam solusi ini mengejek memperkenalkan kalimat if untuk kode produksi karena hanya konstruktor mengejek yang menyediakan instance dari antarmuka.
Saat menulis ini, saya menyadari bahwa blok coba-akhirnya agak tidak terkait karena ada untuk menangani pengguna mengubah lokasi selama waktu aplikasi dijalankan.
Secara keseluruhan rasanya bau, bagaimana mungkin ditangani lebih baik?
mocking
code-smell
kristian mo
sumber
sumber
ReaderConsumer
mandiriReaderImplementation
?Jawaban:
Alih-alih menginisialisasi pembaca dari metode Anda, pindahkan baris ini
Ke dalam konstruktor tanpa parameter default.
Tidak ada yang namanya "mock constructor", jika kelas Anda memiliki ketergantungan yang diperlukan agar dapat berfungsi, maka konstruktor harus menyediakan hal itu, atau membuatnya.
sumber
Anda hanya memerlukan konstruktor tunggal:
dalam kode produksi Anda:
dalam tes Anda:
sumber
Lihat ke Injeksi Ketergantungan dan Inversi Kontrol
Baik Ewan dan RubberDuck memiliki jawaban yang sangat baik. Tapi saya ingin menyebutkan area lain untuk melihat ke mana Dependency Injection (DI) dan Inversion of Control (IoC). Kedua pendekatan ini memindahkan masalah yang Anda alami ke dalam kerangka / pustaka sehingga Anda tidak perlu khawatir tentang hal itu.
Contoh Anda sederhana, dan cepat dibuang, tetapi, mau tidak mau Anda akan membangun di atasnya dan Anda akan berakhir dengan ton konstruktor atau rutin inisialisasi yang terlihat seperti:
var foo = Foo baru (Bilah baru (Baz baru (), Quz baru ()), Foo2 baru ());
Dengan DI / IoC Anda menggunakan pustaka yang memungkinkan Anda untuk menjabarkan aturan untuk mencocokkan antarmuka dengan implementasi dan kemudian Anda hanya mengatakan "Beri aku Foo" dan itu berhasil bagaimana memasang semuanya.
Ada banyak Kontainer IoC yang sangat ramah (begitu sebutannya) di luar sana, dan saya akan merekomendasikan satu untuk dilihat, tetapi, silakan jelajahi, karena ada banyak sekali pilihan bagus.
Yang sederhana untuk memulai adalah:
http://www.ninject.org/
Berikut daftar untuk dijelajahi:
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
sumber