Autofixture: Secara opsional nonaktifkan caching untuk AutoMoq?

Dibuat pada 20 Mei 2016  ·  14Komentar  ·  Sumber: AutoFixture/AutoFixture

Saat menggunakan AutoConfiguredMoqCustomization, nilai yang dikembalikan oleh perlengkapan yang digunakan di-cache, dan nilai yang sama akan dikembalikan pada setiap permintaan (saya tidak yakin apakah ini dilakukan di MockType.ReturnsUsingContext atau di tempat lain, tapi saya melihat komentar tentangnya pada jalur 104 di sana).

Satu-satunya cara yang saya temukan untuk menimpanya adalah dengan meneruskan contoh Frozen dari tiruan yang dimaksud ke dalam metode pengujian, dan menimpa pengaturan dengan fungsi yang menjalankan perlengkapan:

someMock.Setup(it => it.SomeMethodReturningAString()).Returns(() => fixture.Create<string>())

Apakah ada cara yang lebih umum/lebih cerdas untuk mengonfigurasi tiruan yang dibuat secara otomatis untuk memanggil fixture setiap kali nilai diperlukan dari AutoFixture, selain secara manual mengatur setiap permintaan?

enhancement good first issue

Komentar yang paling membantu

Saya akui bahwa saya pikir tes ganda dikonfigurasi untuk memanggil kembali ke AutoFixture untuk mendapatkan nilai kembali. AutoFixture sudah memiliki mekanisme manajemen seumur hidup (melalui fitur Freeze-nya), jadi saya merasa agak mengejutkan bahwa AutoConfiguredMoqCustomization mengimplementasikan pengelola seumur hidup sendiri, dan dengan demikian mengesampingkan permukaan kontrol yang disediakan oleh AutoFixture sendiri.

Semua 14 komentar

Gagasan di balik caching nilai hasil adalah membuat semua metode _pure_ secara default, yang dianggap sebagai praktik yang baik.

Jika sistem yang diuji mengharapkan fungsi murni, tetapi diberikan fungsi tidak murni, pengujian kemungkinan akan menghasilkan positif palsu. Misalnya

// This method will return the expected result *if* `GetInt` is pure.
int Double(IDependency dep) {
    return dep.GetInt() + dep.GetInt();
}

Assert.Equal(dep.GetInt * 2, Double(dep));

Di sisi lain, jika sistem yang diuji tidak mengasumsikan kemurnian, memberikannya fungsi murni atau tidak murni seharusnya tidak ada bedanya.

Oleh karena itu, default ke fungsi murni masuk akal bagi saya ketika saya menerapkan fitur ini.

Apakah ada cara yang lebih umum/lebih cerdas untuk mengonfigurasi tiruan yang dibuat secara otomatis untuk memanggil fixture setiap kali nilai diperlukan dari AutoFixture, selain secara manual mengatur setiap permintaan?

Jika Anda perlu melakukan ini untuk metode _one_, tetapi di beberapa pengujian, saya akan memasukkannya ke dalam IConfiguration dapat digunakan kembali.

Jika Anda ingin melakukan ini untuk semua metode, di beberapa pengujian, maka Anda perlu sedikit lebih banyak pekerjaan:

  • Tentukan implementasi baru dari ReturnsUsingContext (IIRC, Anda cukup menyalin implementasi saat ini dan menghapus baris 104)
  • Definisikan ulang MockVirtualMethodsCommand dan ganti panggilan ke ReturnsUsingContext dengan panggilan ke metode baru Anda.
  • Definisikan ulang AutoConfiguredMoqCustomization dan ganti instantiasi MockVirtualMethodsCommand dengan instantiasi kelas baru Anda.

Kami juga dapat memikirkan cara untuk membuat perilaku ini dapat dikonfigurasi, tetapi saya tidak yakin apakah permintaannya cukup tinggi untuk membenarkan hal ini. Perubahan seperti itu tidak boleh dianggap enteng, menurut pendapat saya - penyesuaian halus dapat menyebabkan kompleksitas yang tidak disengaja. @ploeh , apa pendapat Anda tentang ini?

Saya akui bahwa saya pikir tes ganda dikonfigurasi untuk memanggil kembali ke AutoFixture untuk mendapatkan nilai kembali. AutoFixture sudah memiliki mekanisme manajemen seumur hidup (melalui fitur Freeze-nya), jadi saya merasa agak mengejutkan bahwa AutoConfiguredMoqCustomization mengimplementasikan pengelola seumur hidup sendiri, dan dengan demikian mengesampingkan permukaan kontrol yang disediakan oleh AutoFixture sendiri.

Itu poin yang sangat bagus, saya tidak pernah berpikir tentang Freeze seperti itu. Mengubah perilaku kustomisasi sekarang akan menjadi perubahan besar, saya percaya... apakah menurut Anda itu harus diubah di AutoFixture v4?

Apakah itu perilaku yang telah kami dokumentasikan atau entah bagaimana 'dijanjikan' dalam pengujian?

Anehnya, tidak. Saya cukup yakin saya telah membahas ini, tetapi tampaknya saya tidak melakukannya. Setidaknya saya tidak dapat menemukan tes apa pun yang mencakup ini, dan menghapus baris itu tidak menyebabkan tes apa pun gagal. Namun, IMO, itu masih merupakan perilaku yang dapat diamati, dan kemungkinan ada kode yang bergantung pada ini ...

Poin yang adil. Mungkinkah nilai konfigurasi yang kita setel ke satu nilai sekarang, dan kemudian mengubahnya saat kita beralih ke AutoFixture 4?

Sepakat. Dalam konteks ini, apa sebenarnya yang Anda maksud dengan "nilai konfigurasi"? Apakah mengangkatnya ke const di dalam kelas MockType sudah cukup? Misalnya, private const bool cacheReturnValues = true lalu if(cacheReturnValues) /**/

Saya akui, itu sedikit komentar yang dibuang, jadi saya tidak tahu apakah itu mungkin dilakukan tanpa terlalu banyak perubahan. Namun, yang saya maksud adalah ini:

@andreasnilsen ingin mengubah perilaku sekarang, tetapi kami khawatir itu akan menjadi perubahan yang merusak. Jika kami membuat perilaku dapat dikonfigurasi, maka kami akan memberikan @andreasnilsen cara untuk mengubah perilaku sekarang, sementara kami tidak merusak klien lain.

Saat kami memperkenalkan AutoFixture 4, kami mengubah konfigurasi default, sehingga perilaku defaultnya adalah nilai yang dikembalikan tidak di-cache. Atau mungkin kita cukup menghapus opsi itu...

Sesuatu seperti boolean cacheReturnValues bisa menjadi salah satu cara untuk melakukannya, tapi kita harus mengaktifkan klien untuk mengubah nilainya, jadi tidak bisa private .

(Juga, kecuali jika kita benar-benar yakin bahwa hanya akan ada tepat dua nilai, kita harus mempertimbangkan enum alih-alih bool .)

Ah, pertama-tama saya pikir maksud Anda adalah beberapa bendera internal yang mudah dikenali dan diubah di v4.

Dua pendekatan pertama yang muncul dalam pikiran adalah:

  • Cukup tambahkan parameter boolean (opsional, untuk kompatibilitas mundur) ke konstruktor AutoConfiguredMoqCustomization , yang kemudian akan disebarkan ke MockVirtualMethodsCommand dan ke internal MockType.ReturnsUsingContext . Ini tampaknya:

    1. agak berbelit-belit dan

    2. terlalu _ad hoc_. Jika kita ingin menambahkan lebih banyak parameter konfigurasi ke kustomisasi, konstruktor akan menjadi terlalu rumit dan sulit untuk digunakan/dipelihara.

  • Gunakan pola objek parameter untuk menyelesaikan masalah (ii) di atas.

Saya berhati-hati dalam membuat keputusan desain yang mungkin akan kami sesali dan terjebak di kemudian hari, jadi keahlian/pengalaman Anda dalam mengelola proyek ini akan sangat dihargai.

Saya sedang memikirkan sesuatu seperti Strategi ...

Ah ya, tentu saja! Saya kira saya terpaku pada "nilai konfigurasi" dan lupa untuk mundur selangkah.

Saya minta maaf atas jawaban yang terlambat, saya telah kebanjiran - Saya akan segera melihatnya dan kembali dengan proposal desain.

Baru-baru ini kami telah melakukan refactoring kustomisasi untuk menggunakan properti untuk penyesuaian kustomisasi. Secara potensial, fitur ini dapat dikontrol seperti berikut (temukan nama pengaturan yang lebih baik):
c# new AutoMoqCustomization { CacheCallResults = false }

Di bawah tenda kita bisa menerapkannya melalui strategi yang berbeda seperti yang telah disarankan di atas.

Menandai dengan tag lompatan, karena penerapannya seharusnya relatif mudah.

@zvirja dapatkah Anda membantu saya sedikit dan saya dapat mengerjakan yang ini. Saya hanya tidak tahu harus mulai dari mana :)

@micheleissa Terima kasih atas minat Anda! Saya sarankan hanya membaca kode sumber AutoMoq dan men-debugnya untuk memahami mekanisme internal. Ini sangat kecil, jadi seharusnya tidak memakan banyak waktu ...

Jika Anda memiliki pertanyaan yang lebih spesifik, silakan tanyakan

Apakah halaman ini membantu?
0 / 5 - 0 peringkat