Cara menguji unit metode statis di C #

Saat membangun atau mengerjakan aplikasi .NET Anda mungkin sering menggunakan metode statis. Metode dalam C # dapat berupa statis atau non-statis. Metode non-statis (juga dikenal sebagai metode instance) dapat dipanggil pada instance kelas tempatnya. Metode statis tidak memerlukan instance kelas untuk dipanggil - metode statis dapat dipanggil pada kelas itu sendiri.

Meskipun menguji metode non-statis (setidaknya yang tidak memanggil metode statis atau berinteraksi dengan dependensi eksternal) sangatlah mudah, menguji metode statis bukanlah tugas yang mudah. Artikel ini berbicara tentang bagaimana Anda dapat mengatasi tantangan ini dan menguji metode statis di C #. 

[Juga tentang: Cara merefaktor objek Dewa di C #]

Untuk bekerja dengan contoh kode yang disediakan dalam artikel ini, Anda harus menginstal Visual Studio 2019 di sistem Anda. Jika Anda belum memiliki salinannya, Anda dapat mengunduh Visual Studio 2019 di sini.  

Buat proyek aplikasi konsol inti .NET di Visual Studio .NET

Pertama, mari buat proyek Aplikasi Konsol Inti .NET di Visual Studio. Dengan asumsi Visual Studio 2019 diinstal di sistem Anda, ikuti langkah-langkah yang diuraikan di bawah ini untuk membuat proyek aplikasi konsol .NET Core baru di Visual Studio.

  1. Luncurkan Visual Studio IDE.
  2. Klik "Buat proyek baru".
  3. Di jendela "Buat proyek baru", pilih "Aplikasi Konsol (.NET Core)" dari daftar template yang ditampilkan.
  4. Klik Next.
  5. Di jendela "Configure your new project" yang ditampilkan berikutnya, tentukan nama dan lokasi untuk proyek baru tersebut.
  6. Klik Buat. 

Ini akan membuat proyek aplikasi konsol .NET Core baru di Visual Studio 2019. Dengan cara yang sama, buat dua proyek lagi - perpustakaan kelas dan proyek unit test (xUnit test). Kami akan menggunakan tiga proyek ini untuk mengilustrasikan pengujian unit metode statis di bagian selanjutnya dari artikel ini.

Ketika metode statis dapat dan tidak dapat diuji unit

Pengujian unit metode statis tidak berbeda dengan pengujian unit metode non-statis. Metode statis tidak dapat diuji sendiri. Metode statis yang tidak memiliki status atau tidak mengubah status dapat diuji unitnya. Selama metode dan dependensinya idempoten, metode tersebut dapat diuji unitnya. Masalah muncul saat metode statis memanggil metode lain atau saat objek yang diuji memanggil metode statis. Di sisi lain, jika objek yang diuji memanggil metode instance, Anda dapat mengujinya dengan mudah.

Metode statis tidak dapat diuji unit jika salah satu dari berikut ini benar: 

  • Metode statis berinteraksi dengan dependensi eksternal seperti database, sistem file, jaringan, atau API eksternal.
  • Metode statis menyimpan informasi status, yaitu jika menyimpan data ke dalam cache objek statis kelas.

Perhatikan potongan kode berikut yang menunjukkan dua kelas, yaitu ProductBL dan Logger. Sementara ProductBL adalah kelas non-statis, Logger adalah kelas statis. Perhatikan bahwa metode Write kelas Logger telah dipanggil dari metode LogMessage kelas ProductBL.

ProductBL kelas publik

    {

        public void LogMessage (pesan string)

        {

            Logger.Write (pesan);

        }

    }

    kelas publik Logger

    {

        public static void Write (pesan string)

        {

           // Tulis kode Anda di sini untuk mencatat data

        }

    }

Asumsikan bahwa metode Write dari kelas Logger terhubung ke database dan kemudian menulis data ke tabel database. Nama database dan tabelnya tempat data harus ditulis mungkin sudah dikonfigurasi sebelumnya di file appsettings.json. Bagaimana Anda sekarang dapat menulis pengujian unit untuk metode ProductBL?

Perhatikan bahwa metode statis tidak dapat diejek dengan mudah. Sebagai contoh, jika Anda memiliki dua kelas bernama A dan B dan kelas A menggunakan anggota statis kelas B, Anda tidak akan dapat menguji unit kelas A secara terpisah.

Tiga cara untuk menguji unit metode statis

Anda dapat menggunakan Moq untuk meniru metode non-statis tetapi tidak dapat digunakan untuk meniru metode statis. Meskipun metode statis tidak dapat diejek dengan mudah, ada beberapa cara untuk meniru metode statis.

Anda dapat memanfaatkan framework Moles atau Fakes dari Microsoft untuk meniru panggilan metode statis. (Kerangka kerja palsu disertakan dalam Visual Studio 2012 sebagai penerus Moles - ini adalah generasi berikutnya dari Moles dan Stubs.) Cara lain untuk meniru panggilan metode statis adalah dengan menggunakan delegasi. Ada cara lain untuk meniru panggilan metode statis dalam aplikasi - dengan menggunakan kelas pembungkus dan injeksi ketergantungan.

IMHO opsi terakhir ini adalah solusi terbaik untuk masalah tersebut. Yang perlu Anda lakukan adalah menggabungkan panggilan metode statis ke dalam metode instance, lalu menggunakan injeksi dependensi untuk memasukkan instance kelas pembungkus ke kelas yang diuji.

Buat kelas pembungkus di C #

Cuplikan kode berikut menggambarkan kelas LogWrapper yang mengimplementasikan antarmuka IWrapper dan membungkus panggilan ke metode Logger.Write () di dalam metode instance yang disebut LogData.

kelas publik LogWrapper: IWrapper

    {

        string _message = null;

        public LogWrapper (pesan string)

        {

            _message = pesan;

        }

        public void LogData (pesan string)

        {

            _message = pesan;

            Logger.Write (_message);

        }

    }

Potongan kode berikut menunjukkan antarmuka IWrapper. Ini berisi deklarasi metode LogData.

antarmuka publik IWrapper

    {

        void LogData (pesan string);

    }

Kelas ProductBL menggunakan injeksi ketergantungan (injeksi konstruktor) untuk memasukkan instance kelas LogWrapper seperti yang ditunjukkan dalam daftar kode yang diberikan di bawah ini.

ProductBL kelas publik

    {

        hanya baca IWrapper _wrapper;

        string statis _message = null;

        ProductBL publik (pembungkus IWrapper)

        {

            _wrapper = pembungkus;

        }

        public void LogMessage (pesan string)

        {

            _message = pesan;

            _wrapper.LogData (_message);

        }

    }

Metode LogMessage kelas ProductBL memanggil metode LogData pada contoh kelas LogWrapper yang telah diinjeksi sebelumnya.

Gunakan xUnit dan Moq untuk membuat metode pengujian unit di C #

Buka file UnitTest1.cs dan ganti nama kelas UnitTest1 menjadi UnitTestForStaticMethodsDemo. File UnitTest1.cs secara otomatis akan diganti namanya menjadi UnitTestForStaticMethodsDemo.cs. Kami sekarang akan memanfaatkan kerangka kerja Moq untuk menyiapkan, menguji, dan memverifikasi tiruan.

Potongan kode berikut mengilustrasikan bagaimana Anda dapat menggunakan kerangka kerja Moq untuk menyatukan metode pengujian di C #.

var mock = new Mock ();

mock.Setup (x => x.LogData (It.IsAny ()));

ProductBL baru (mock.Object) .LogMessage ("Hello World!");

mock.VerifyAll ();

Saat Anda menjalankan pengujian, berikut tampilan output di Jendela Test Explorer.

Daftar kode lengkap dari kelas tes diberikan di bawah ini untuk referensi Anda.

public class UnitTestForStaticMethodsDemo

    {

        [Fakta]

        public void StaticMethodTest ()

        {

            var mock = new Mock ();

            mock.Setup (x => x.LogData (It.IsAny ()));

            ProductBL baru (mock.Object) .LogMessage ("Hello World!");

            mock.VerifyAll ();

        }

    }

Pengujian unit adalah proses yang menguji unit kode dalam aplikasi untuk memeriksa apakah hasil aktual dari pengujian unit Anda sesuai dengan hasil yang diinginkan. Jika digunakan dengan bijaksana, pengujian unit dapat membantu mencegah bug dalam fase pengembangan proyek.

Metode statis dapat menimbulkan sejumlah masalah saat Anda mencoba untuk mengujinya menggunakan tiruan. Jika aplikasi Anda mengharuskan Anda untuk meniru metode statis, Anda harus mempertimbangkan bahwa desain berbau - yaitu, indikator desain yang buruk. Saya akan membahas ejekan, pemalsuan, dan rintisan secara lebih rinci dalam artikel mendatang di sini.

Bagaimana melakukan lebih banyak di C #:

  • Cara refactor objek Tuhan di C #
  • Cara menggunakan ValueTask di C #
  • Cara menggunakan kekekalan di C
  • Cara menggunakan const, readonly, dan static di C #
  • Cara menggunakan anotasi data di C #
  • Cara bekerja dengan GUID di C # 8
  • Kapan menggunakan kelas abstrak vs. antarmuka di C #
  • Bagaimana bekerja dengan AutoMapper di C #
  • Cara menggunakan ekspresi lambda di C #
  • Cara bekerja dengan delegasi Action, Func, dan Predicate di C #
  • Bagaimana bekerja dengan delegasi di C #
  • Bagaimana menerapkan logger sederhana di C #
  • Bagaimana bekerja dengan atribut di C #
  • Bagaimana bekerja dengan log4net di C #
  • Bagaimana menerapkan pola desain repositori di C #
  • Bagaimana bekerja dengan refleksi di C #
  • Bagaimana bekerja dengan filesystemwatcher di C #
  • Bagaimana melakukan inisialisasi malas di C #
  • Bagaimana bekerja dengan MSMQ di C #
  • Bagaimana bekerja dengan metode ekstensi di C #
  • Bagaimana kami ekspresi lambda di C #
  • Kapan menggunakan kata kunci volatile di C #
  • Cara menggunakan kata kunci hasil di C #
  • Bagaimana menerapkan polimorfisme di C #
  • Cara membuat penjadwal tugas Anda sendiri di C #
  • Bagaimana bekerja dengan RabbitMQ di C #
  • Bagaimana bekerja dengan tupel di C #
  • Menjelajahi metode virtual dan abstrak di C #
  • Cara menggunakan Dapper ORM di C #
  • Cara menggunakan pola desain kelas terbang di C #