Preferensi saya adalah memiliki kelas yang menggunakan waktu sebenarnya bergantung pada antarmuka, seperti
interface IClock
{
DateTime Now { get; }
}
Dengan implementasi yang konkrit
class SystemClock: IClock
{
DateTime Now { get { return DateTime.Now; } }
}
Kemudian jika mau, Anda dapat menyediakan jenis jam lain yang Anda inginkan untuk pengujian, seperti
class StaticClock: IClock
{
DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}
Mungkin ada beberapa overhead dalam menyediakan jam ke kelas yang bergantung padanya, tetapi itu dapat ditangani oleh sejumlah solusi injeksi ketergantungan (menggunakan wadah Pembalikan Kontrol, injeksi konstruktor / penyetel lama biasa, atau bahkan Pola Gerbang Statis ).
Mekanisme lain untuk mengirimkan objek atau metode yang menyediakan waktu yang diinginkan juga berfungsi, tetapi menurut saya kuncinya adalah menghindari menyetel ulang jam sistem, karena itu hanya akan menimbulkan rasa sakit di level lain.
Selain itu, menggunakan DateTime.Now
dan memasukkannya ke dalam kalkulasi Anda tidak hanya terasa tidak tepat - ini merampas kemampuan Anda untuk menguji waktu tertentu, misalnya jika Anda menemukan bug yang hanya terjadi di dekat batas tengah malam, atau pada hari Selasa. Menggunakan waktu saat ini tidak memungkinkan Anda untuk menguji skenario tersebut. Atau setidaknya tidak kapan pun Anda mau.
UtcNow
harus digunakan dan kemudian disesuaikan secara tepat sesuai dengan perhatian kode, misalnya logika bisnis, UI, dll. Manipulasi DateTime melintasi zona waktu adalah ladang ranjau tetapi langkah pertama yang terbaik ke depan adalah selalu memulai dengan Waktu UTC.Ayende Rahien menggunakan metode statis yang cukup sederhana ...
sumber
Saya pikir membuat kelas jam terpisah untuk sesuatu yang sederhana seperti mendapatkan tanggal saat ini agak berlebihan.
Anda dapat melewatkan tanggal hari ini sebagai parameter sehingga Anda dapat memasukkan tanggal yang berbeda dalam pengujian. Ini memiliki keuntungan tambahan yaitu membuat kode Anda lebih fleksibel.
sumber
Menggunakan Microsoft Fakes untuk membuat shim adalah cara yang sangat mudah untuk melakukan ini. Misalkan saya memiliki kelas berikut:
Dalam Visual Studio 2012 Anda dapat menambahkan rakitan Fakes ke proyek pengujian Anda dengan mengklik kanan rakitan yang ingin Anda buat Fakes / Shims dan memilih "Add Fakes Assembly"
Terakhir, kelas pengujian akan terlihat seperti ini:
sumber
Kunci sukses unit testing adalah decoupling . Anda harus memisahkan kode yang menarik dari dependensi eksternalnya, sehingga dapat diuji secara terpisah. (Untungnya, Test-Driven Development menghasilkan kode terpisah.)
Dalam hal ini, eksternal Anda adalah DateTime saat ini.
Saran saya di sini adalah mengekstrak logika yang berhubungan dengan DateTime ke metode atau kelas baru atau apa pun yang masuk akal dalam kasus Anda, dan meneruskan DateTime masuk Sekarang, pengujian unit Anda dapat meneruskan DateTime sewenang-wenang, untuk menghasilkan hasil yang dapat diprediksi.
sumber
Yang lain menggunakan Microsoft Moles ( kerangka Isolasi untuk .NET ).
sumber
Saya sarankan menggunakan pola IDisposable:
Secara rinci dijelaskan di sini: http://www.lesnikowski.com/blog/index.php/testing-datetime-now/
sumber
Jawaban sederhana: parit System.DateTime :) Sebagai gantinya, gunakan NodaTime dan pustaka pengujiannya: NodaTime.Testing .
Bacaan lebih lanjut:
sumber
Anda dapat memasukkan kelas (lebih baik: metode / delegasi ) yang Anda gunakan untuk
DateTime.Now
di kelas yang diuji. TelahDateTime.Now
menjadi nilai default dan hanya mengaturnya dalam pengujian ke metode dummy yang mengembalikan nilai konstan.EDIT: Apa yang dikatakan Blair Conrad (dia memiliki beberapa kode untuk dilihat). Kecuali, saya cenderung lebih suka delegasi untuk ini, karena mereka tidak mengacaukan hierarki kelas Anda dengan hal-hal seperti
IClock
...sumber
Saya sering menghadapi situasi ini, sehingga saya membuat nuget sederhana yang mengekspos properti Now melalui antarmuka.
Penerapannya tentu saja sangat mudah
Jadi setelah menambahkan nuget ke proyek saya, saya dapat menggunakannya dalam pengujian unit
Anda dapat menginstal modul langsung dari GUI Nuget Package Manager atau dengan menggunakan perintah:
Dan kode untuk Nuget ada di sini .
Contoh penggunaan dengan Autofac dapat ditemukan di sini .
sumber
Pernahkah Anda mempertimbangkan untuk menggunakan kompilasi bersyarat untuk mengontrol apa yang terjadi selama debug / penerapan?
misalnya
Jika gagal, Anda ingin mengekspos properti agar dapat memanipulasinya, ini semua adalah bagian dari tantangan menulis kode yang dapat diuji , yang saat ini sedang saya geluti sendiri: D
Edit
Sebagian besar dari diri saya lebih menyukai pendekatan Blair . Ini memungkinkan Anda untuk "menyambungkan" bagian kode untuk membantu pengujian. Itu semua mengikuti prinsip desain merangkum apa yang bervariasi kode uji tidak berbeda dengan kode produksi, hanya saja tidak ada yang pernah melihatnya secara eksternal.
Membuat dan antarmuka mungkin tampak seperti banyak pekerjaan untuk contoh ini meskipun (itulah sebabnya saya memilih kompilasi bersyarat).
sumber
DateTime
'sNow
danToday
lain