Menggunakan Moq dan melihat Callback
tetapi saya belum dapat menemukan contoh sederhana untuk memahami cara menggunakannya.
Apakah Anda memiliki potongan kecil yang berfungsi yang dengan jelas menjelaskan bagaimana dan kapan menggunakannya?
Menggunakan Moq dan melihat Callback
tetapi saya belum dapat menemukan contoh sederhana untuk memahami cara menggunakannya.
Apakah Anda memiliki potongan kecil yang berfungsi yang dengan jelas menjelaskan bagaimana dan kapan menggunakannya?
Jawaban:
Sulit dikalahkan https://github.com/Moq/moq4/wiki/Quickstart
Jika itu tidak cukup jelas, saya akan menyebutnya bug dokumen ...
EDIT: Sebagai tanggapan atas klarifikasi Anda ...
Untuk setiap metode tiruan yang Setup
Anda lakukan, Anda dapat menunjukkan hal-hal seperti:
The .Callback
Mekanisme mengatakan "Saya tidak bisa menjelaskan sekarang, tapi ketika panggilan berbentuk seperti ini terjadi, memanggil saya kembali dan saya akan melakukan apa yang perlu dilakukan". Sebagai bagian dari rantai panggilan fasih yang sama, Anda dapat mengontrol hasil untuk dikembalikan (jika ada) melalui .Returns
". Dalam contoh QS, contohnya adalah mereka membuat nilai yang dikembalikan meningkat setiap waktu.
Secara umum, Anda tidak akan membutuhkan mekanisme seperti ini terlalu sering (Pola Tes xUnit memiliki istilah untuk antipatterns dari Tes Logika Bersyarat sejenisnya), dan jika ada cara yang lebih sederhana atau built-in untuk menetapkan apa yang Anda butuhkan, itu harus digunakan dalam preferensi.
Bagian 3 dari 4 dalam seri Moq Justin Etheredge mencakupnya, dan ada contoh callback lain di sini
Contoh sederhana dari panggilan balik dapat ditemukan di Menggunakan Panggilan Balik dengan posting Moq .
Callback
tidak ada hubungannya dengan nilai pengembalian (kecuali jika Anda menghubungkannya melalui kode). Pada dasarnya ini hanya memastikan callback dipanggil sebelum atau setelah setiap pemanggilan (tergantung apakah Anda menghubungkannya sebelum atau sesudah masing- Returns
masing), polos dan sederhana.
Berikut adalah contoh penggunaan callback untuk menguji entitas yang dikirim ke Layanan Data yang menangani penyisipan.
var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback((DataEntity de) => insertedEntity = de);
Sintaks metode generik alternatif:
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback<DataEntity>(de => insertedEntity = de);
Kemudian Anda dapat menguji sesuatu seperti
Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");
It.Is<T>
in a Mock.Verify
daripada mengotori pengujian dengan temps. Tetapi +1 karena saya yakin ada banyak orang yang akan bekerja paling baik dari sebuah contoh.
Ada dua jenis Callback
dalam Moq. Satu terjadi sebelum panggilan kembali; yang lainnya terjadi setelah panggilan kembali.
var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
.Callback((x, y) =>
{
message = "Rally on!";
Console.WriteLine($"args before returns {x} {y}");
})
.Returns(message) // Rally on!
.Callback((x, y) =>
{
message = "Rally over!";
Console.WriteLine("arg after returns {x} {y}");
});
Di kedua panggilan balik, kita dapat:
Callback
hanyalah sarana untuk mengeksekusi kode kustom yang Anda inginkan saat panggilan dilakukan ke salah satu metode tiruan. Berikut contoh sederhananya:
public interface IFoo
{
int Bar(bool b);
}
var mock = new Mock<IFoo>();
mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
.Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
.Returns(42);
var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);
// output:
// Bar called with: True
// Result: 42
Saya baru-baru ini menemukan kasus penggunaan yang menarik untuk itu. Misalkan Anda mengharapkan beberapa panggilan ke tiruan Anda, tetapi itu terjadi secara bersamaan. Jadi, Anda tidak memiliki cara untuk mengetahui urutan panggilan mereka, tetapi Anda ingin mengetahui panggilan yang Anda harapkan terjadi (terlepas dari urutannya). Anda bisa melakukan sesuatu seperti ini:
var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));
// output:
// Invocations: True, False
BTW tidak bingung dengan perbedaan "sebelum Returns
" dan "setelah Returns
" yang menyesatkan . Ini hanyalah perbedaan teknis tentang apakah kode kustom Anda akan berjalan setelah Returns
dievaluasi atau sebelumnya. Di mata pemanggil, keduanya akan berjalan sebelum nilainya dikembalikan. Memang, jika metodenya void
-kembali, Anda bahkan tidak dapat memanggil Returns
namun berfungsi sama. Untuk informasi lebih lanjut, lihat https://stackoverflow.com/a/28727099/67824 .
Di atas jawaban bagus lainnya di sini, saya telah menggunakannya untuk melakukan logika sebelum membuat pengecualian. Misalnya, saya perlu menyimpan semua objek yang diteruskan ke suatu metode untuk verifikasi nanti, dan metode itu (dalam beberapa kasus uji) perlu membuat pengecualian. Memanggil .Throws(...)
pada Mock.Setup(...)
menimpa para Callback()
tindakan dan tidak pernah menyebutnya. Namun, dengan memberikan pengecualian dalam Callback, Anda masih dapat melakukan semua hal baik yang ditawarkan oleh callback, dan tetap memberikan pengecualian.