Menggunakan IoC untuk Pengujian Unit

97

Bagaimana Kontainer IoC dapat digunakan untuk pengujian unit? Apakah berguna untuk mengelola tiruan dalam solusi besar (50+ proyek) menggunakan IoC? Ada pengalaman? Pustaka C # apa saja yang bekerja dengan baik untuk menggunakannya dalam pengujian unit?

crauscher
sumber
7
@Mark Seemann akan terlalu rendah hati untuk menunjukkannya, tetapi jika Anda tertarik dengan pertanyaan ini, Anda setidaknya harus mengetahui tentang AutoFixture
Ruben Bartelink
1
Ada pembicaraan bagus tentang hubungan antara DI dan ejekan di Vimeo oleh Miguel Castro: vimeo.com/68390510
GregC

Jawaban:

131

Secara umum, DI Container tidak diperlukan untuk unit testing karena unit testing adalah tentang memisahkan tanggung jawab.

Pertimbangkan kelas yang menggunakan Pembuat Injeksi

public MyClass(IMyDependency dep) { }

Di seluruh aplikasi Anda, mungkin ada grafik ketergantungan besar yang tersembunyi di baliknya IMyDependency, tetapi dalam pengujian unit, Anda meratakan semuanya menjadi satu Tes Ganda .

Anda dapat menggunakan tiruan dinamis seperti Moq atau RhinoMock untuk menghasilkan Test Double, tetapi itu tidak diperlukan.

var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);

Dalam beberapa kasus, container auto-mocking bagus untuk dimiliki, tetapi Anda tidak perlu menggunakan DI Container yang sama dengan yang digunakan aplikasi produksi.

Mark Seemann
sumber
13
setuju ... kecuali target pengujian memiliki wadah IoC sebagai ketergantungan, pengujian Anda seharusnya tidak memerlukannya ... Anda akan menghapus sebagian besar grafik objek saat melakukan pengujian unit.
Anderson Imes
4
@ Mark Seemann Ini masuk akal ... Tapi bagaimana dengan tes integrasi? Yaitu, saya bermain-main dengan tes UI dan saya menghadapi situasi ketika saya harus berbagi root komposisi. Ada komentar?
Arnis Lapsa
5
@Arnis L .: Untuk pengujian integrasi, ini kurang penting. Anda dapat memilih untuk menggunakan Kontainer DI untuk menyambungkan komponen, tetapi jika demikian, Anda mungkin memerlukan konfigurasi yang berbeda untuk wadah daripada dalam aplikasi lengkap - kecuali jika Anda melakukan Uji Subkutan atau Uji Sistem lengkap, dalam hal ini Anda dapat menggunakan kembali konfigurasi aplikasi Container.
Mark Seemann
ref ke majalah
msdn
18

Bagaimana Ioc Container digunakan untuk pengujian unit?

IoC akan memberlakukan paradigma pemrograman yang akan membuat pengujian unit dalam isolasi (yaitu menggunakan tiruan) lebih mudah: penggunaan antarmuka, tidak ada yang baru (), tidak ada lajang ...

Tetapi menggunakan wadah IoC untuk pengujian sebenarnya bukan persyaratan, itu hanya akan menyediakan beberapa fasilitas misalnya injeksi tiruan tetapi Anda dapat melakukannya secara manual.

Apakah berguna untuk mengelola tiruan dalam solusi besar (50+ proyek) menggunakan IoC?

Saya tidak yakin apa yang Anda maksud dengan mengelola ejekan menggunakan IoC. Bagaimanapun, wadah IoC biasanya dapat melakukan lebih dari sekadar menyuntikkan tiruan ketika datang ke pengujian. Dan jika Anda memiliki dukungan IDE yang layak yang memungkinkan pemfaktoran ulang, mengapa tidak menggunakannya?

Ada pengalaman?

Ya, pada solusi besar, Anda membutuhkan lebih dari sebelumnya solusi yang tidak rawan kesalahan dan refactoring-merugikan (yaitu baik melalui wadah IoC yang aman atau dukungan IDE yang baik).

Pascal Thivent
sumber
17

Saya sering menggunakan wadah IoC dalam pengujian saya. Memang, itu bukan "tes unit" dalam arti murni. IMO Mereka lebih BDDish dan memfasilitasi refactoring. Tes ada untuk memberi Anda kepercayaan diri untuk refactor. Tes yang ditulis dengan buruk bisa seperti menuangkan semen ke dalam kode Anda.

Pertimbangkan hal berikut:

[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
    [Test]
    public void Should_save_image()
    {
        container.ConfigureMockFor<IFileRepository>()
            .Setup(r => r.Create(It.IsAny<IFile>()))
            .Verifiable();

        AddToGallery(new RequestWithRealFile());

        container.VerifyMockFor<IFileRepository>();
    }

    private void AddToGallery(AddBusinessImage request)
    {
        container.Resolve<BusinessPublisher>().Consume(request);
    }
}

Ada beberapa hal yang terjadi saat menambahkan gambar ke galeri. Gambar diubah ukurannya, thumbnail dibuat, dan file disimpan di AmazonS3. Dengan menggunakan wadah, saya dapat lebih mudah mengisolasi hanya perilaku yang ingin saya uji, yang dalam hal ini adalah bagian yang bertahan.

Ekstensi penampung tiruan otomatis berguna saat menggunakan teknik ini: http://www.agileatwork.com/auto-mocking-unity-container-extension/

Mike Valenty
sumber
8
1 untuk frase "seperti menuangkan semen ke dalam kode Anda". Saya sudah mulai menggunakannya setiap saat.
Andrew Shepherd
2

Menggunakan kontainer dengan kemampuan untuk menyelesaikan layanan yang tidak terdaftar / tidak dikenal seperti SimpleInjector , DryIoc (tambangnya) dapat mengembalikan tiruan untuk antarmuka yang belum diimplementasikan.

Artinya, Anda dapat memulai pengembangan dengan implementasi sederhana pertama dan dependensi tiruannya, dan menggantinya dengan yang nyata saat Anda maju.

dadhi
sumber