Domain saya terdiri dari banyak kelas sederhana yang tidak dapat diubah seperti ini:
public class Person
{
public string FullName { get; }
public string NameAtBirth { get; }
public string TaxId { get; }
public PhoneNumber PhoneNumber { get; }
public Address Address { get; }
public Person(
string fullName,
string nameAtBirth,
string taxId,
PhoneNumber phoneNumber,
Address address)
{
if (fullName == null)
throw new ArgumentNullException(nameof(fullName));
if (nameAtBirth == null)
throw new ArgumentNullException(nameof(nameAtBirth));
if (taxId == null)
throw new ArgumentNullException(nameof(taxId));
if (phoneNumber == null)
throw new ArgumentNullException(nameof(phoneNumber));
if (address == null)
throw new ArgumentNullException(nameof(address));
FullName = fullName;
NameAtBirth = nameAtBirth;
TaxId = taxId;
PhoneNumber = phoneNumber;
Address = address;
}
}
Menulis cek nol dan inisialisasi properti sudah sangat membosankan tetapi saat ini saya menulis tes unit untuk masing-masing kelas untuk memverifikasi bahwa validasi argumen berfungsi dengan benar dan bahwa semua properti diinisialisasi. Ini terasa seperti pekerjaan yang sangat membosankan dengan keuntungan yang tidak sepadan.
Solusi sebenarnya adalah untuk C # untuk mendukung tipe referensi immutability dan non-nullable. Tetapi apa yang dapat saya lakukan untuk memperbaiki situasi sementara itu? Apakah layak menulis semua tes ini? Apakah ide yang baik untuk menulis generator kode untuk kelas seperti itu untuk menghindari tes menulis untuk masing-masing dari mereka?
Inilah yang saya miliki sekarang berdasarkan jawaban.
Saya dapat menyederhanakan cek kosong dan inisialisasi properti agar terlihat seperti ini:
FullName = fullName.ThrowIfNull(nameof(fullName));
NameAtBirth = nameAtBirth.ThrowIfNull(nameof(nameAtBirth));
TaxId = taxId.ThrowIfNull(nameof(taxId));
PhoneNumber = phoneNumber.ThrowIfNull(nameof(phoneNumber));
Address = address.ThrowIfNull(nameof(address));
Menggunakan implementasi berikut oleh Robert Harvey :
public static class ArgumentValidationExtensions
{
public static T ThrowIfNull<T>(this T o, string paramName) where T : class
{
if (o == null)
throw new ArgumentNullException(paramName);
return o;
}
}
Menguji cek nol mudah menggunakan GuardClauseAssertion
dari AutoFixture.Idioms
(terima kasih atas sarannya, Esben Skov Pedersen ):
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(Address).GetConstructors());
Ini dapat dikompresi lebih jauh:
typeof(Address).ShouldNotAcceptNullConstructorArguments();
Menggunakan metode ekstensi ini:
public static void ShouldNotAcceptNullConstructorArguments(this Type type)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(type.GetConstructors());
}