Cara menggunakan Moq untuk memudahkan pengujian unit di C #

Kita sering kali perlu menulis pengujian unit untuk kode yang mengakses sumber daya eksternal seperti database atau sistem file. Jika sumber daya tersebut tidak tersedia, satu-satunya cara untuk memastikan bahwa pengujian dapat dijalankan adalah dengan membuat objek tiruan. Intinya, dengan memanfaatkan implementasi palsu dari dependensi yang mendasari ini, Anda dapat menguji interaksi antara metode yang diuji dan dependensinya. Tiga kerangka kerja tiruan yang paling populer untuk pengembang .Net adalah Rhino Mocks, Moq, dan NMock.

Di antaranya, Moq mungkin yang paling fleksibel dan mudah digunakan. Framework Moq menyediakan cara yang elegan untuk menyiapkan, menguji, dan memverifikasi tiruan. Artikel ini menyajikan diskusi tentang Moq dan bagaimana Moq dapat digunakan untuk mengisolasi unit kode dari dependensinya.

Memulai dengan Moq

Anda dapat menggunakan Moq untuk membuat objek tiruan yang mensimulasikan atau meniru objek nyata. Moq dapat digunakan untuk memalsukan kelas dan antarmuka. Namun, ada beberapa batasan yang harus Anda waspadai. Kelas yang akan diejek tidak boleh statis atau disegel, dan metode yang diejek harus ditandai sebagai virtual. (Perhatikan bahwa ada solusi untuk pembatasan ini. Anda dapat meniru metode statis dengan memanfaatkan pola desain adaptor, misalnya.)

Langkah pertama dalam menggunakan Moq adalah menginstalnya sehingga Anda dapat menggunakannya dalam proyek pengujian unit Anda. Anda dapat mengunduh Moq dari GitHub dan menambahkan referensi yang sesuai. Namun, saya lebih suka menginstal Moq melalui NuGet karena lebih mudah dan kecil kemungkinannya untuk melewatkan referensi. Anda dapat menginstal Moq dengan menggunakan perintah berikut di baris perintah NuGet.

Install-Package Moq

Bagaimana cara mengejek antarmuka menggunakan Moq

Mari kita mulai dengan mengejek sebuah antarmuka. Sintaks untuk membuat objek tiruan menggunakan kelas Mock diberikan di bawah ini.

Mock mockObjectType = Mock baru ();

Sekarang, perhatikan antarmuka berikut bernama IAuthor.

antarmuka publik IAuthor

    {

        int Id {get; set; }

        string FirstName {get; set; }

        string LastName {get; set; }

    }

Menggunakan kerangka kerja Moq, Anda dapat membuat objek tiruan, mengatur nilai properti, menentukan parameter, dan mengembalikan nilai pada pemanggilan metode. Potongan kode berikut menggambarkan bagaimana Anda dapat membuat sebuah instance dari antarmuka IAuthor menggunakan Moq.

var mock = new Mock ();

Perhatikan bahwa kelas Mock milik kerangka kerja Moq dan berisi konstruktor generik yang menerima tipe antarmuka yang ingin Anda buat. Moq memanfaatkan ekspresi lambda, delegasi, dan generik. Semua ini membuat penggunaan framework menjadi sangat intuitif.

Cuplikan kode berikut menunjukkan bagaimana Anda dapat memalsukan antarmuka IAuthor dan memberikan properti contoh palsu dengan nilai yang sesuai. Perhatikan bagaimana kami menggunakan Assert untuk memverifikasi nilai properti dari contoh tiruan.

var author = new Mock ();

author.SetupGet (p => p.Id) .Returns (1);

author.SetupGet (p => p.FirstName) .Returns ("Joydip");

author.SetupGet (p => p.LastName) .Returns ("Kanjilal");

Assert.AreEqual ("Joydip", penulis.Object.FirstName);

Assert.AreEqual (“Kanjilal”, penulis.Object.LastName);

Cara mengejek metode menggunakan Moq

Sekarang mari kita pertimbangkan kelas berikut bernama Artikel. Kelas Artikel hanya berisi satu metode yang disebut GetPublicationDate yang menerima Id artikel sebagai parameter dan mengembalikan tanggal publikasi artikel.

Artikel kelas publik

    {

        DateTime GetPublicationDate publik virtual (int articleId)

        {

            melempar NotImplementedException () baru;

        }

    }

Karena metode GetPublicationDate belum diterapkan di kelas Artikel, metode tersebut telah diolok-olok untuk mengembalikan tanggal saat ini sebagai tanggal publikasi, seperti yang ditunjukkan dalam cuplikan kode yang diberikan di bawah ini.

var mockObj = new Mock ();
mockObj.Setup (x => x.GetPublicationDate (It.IsAny ())). Returns ((int x) => DateTime.Now);

Metode penataan digunakan untuk menentukan perilaku metode yang diteruskan sebagai parameter. Dalam contoh ini, digunakan untuk menentukan perilaku metode GetPublicationDate. Panggilan ke It.IsAny()menyiratkan bahwa metode GetPublicationDate akan menerima parameter tipe integer; Itmengacu pada kelas statis. Metode Pengembalian digunakan untuk menentukan nilai kembalian dari metode yang ditentukan dalam panggilan metode Penataan. Dalam contoh ini, metode Pengembalian digunakan untuk menentukan nilai kembalian metode sebagai tanggal sistem saat ini.

Moq memungkinkan Anda untuk memverifikasi apakah metode atau properti tertentu dipanggil. Cuplikan kode berikut menggambarkan hal ini.

mockObj.Verify (t => t.GetPublicationDate (It.IsAny ()));

Di sini kami menggunakan metode Verify untuk menentukan apakah GetPublicationDate dipanggil pada objek tiruan.

Cara membuat tiruan metode kelas dasar menggunakan Moq

Perhatikan potongan kode berikut. Kami memiliki dua kelas di sini — kelas RepositoryBase dan kelas AuthorRepository yang mengembangkannya.

RepositoryBase kelas abstrak publik

{

    bool virtual publik IsServiceConnectionValid ()

    {

        // Beberapa kode

    }

}

kelas publik AuthorRepository: RepositoryBase

{

    public void Simpan ()

    {

        if (IsServiceConnectionValid ())

        {

            // Beberapa kode

        }

    }

}

Sekarang misalkan kita ingin memeriksa apakah koneksi database valid. Namun, kami mungkin tidak ingin menguji semua kode di dalam metode IsServiceConnectionValid. Misalnya, metode IsServiceConnectionValid mungkin berisi kode yang berkaitan dengan pustaka pihak ketiga. Kami tidak ingin menguji itu, bukan? Di sinilah metode CallBase di Moq datang untuk menyelamatkan. 

Dalam situasi seperti ini, di mana Anda memiliki metode di kelas dasar yang telah diganti dalam tipe tiruan, dan Anda perlu memalsukan versi dasar dari metode yang diganti saja, Anda bisa menggambar di CallBase. Potongan kode berikut menunjukkan bagaimana Anda bisa membuat objek tiruan parsial dari kelas AuthorRepository dengan menyetel properti CallBase ke true.

var mockObj = new Mock () {CallBase = true};

mockObj.Setup (x => x.IsServiceConnectionValid ()). Returns (true);

Kerangka Moq memudahkan pembuatan objek tiruan yang meniru perilaku kelas dan antarmuka untuk pengujian, hanya dengan fungsionalitas yang Anda butuhkan. Untuk lebih lanjut tentang pengujian dengan tiruan, lihat artikel hebat ini dari Martin Fowler.