ما مدى موثوقية التحقق () في موك؟
-
25-09-2019 - |
سؤال
أنا جديد فقط في اختبار الوحدة و ASP.NET MVC. لقد كنت أحاول إدخال رأسي في كل من ستيف ساندرسون "Pro ASP.NET MVC Framework". في الكتاب هناك قطعة من الرمز:
public class AdminController : Controller
{
...
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Product product, HttpPostedFileBase image)
{
...
productsRepository.SaveProduct(product);
TempData["message"] = product.Name + " has been saved.";
return RedirectToAction("Index");
}
}
أنه يختبر مثل ذلك:
[Test]
public void Edit_Action_Saves_Product_To_Repository_And_Redirects_To_Index()
{
// Arrange
AdminController controller = new AdminController(mockRepos.Object);
Product newProduct = new Product();
// Act
var result = (RedirectToRouteResult)controller.Edit(newProduct, null);
// Assert: Saved product to repository and redirected
mockRepos.Verify(x => x.SaveProduct(newProduct));
Assert.AreEqual("Index", result.RouteValues["action"]);
}
يمر الاختبار.
لذلك أفسد الكود عن عمد عن طريق إضافة "ProductRepository.DeleteProduct (المنتج) ؛" بعد "SaveProduct (المنتج) ؛" كما في:
...
productsRepository.SaveProduct(product);
productsRepository.DeleteProduct(product);
...
يمر الاختبار. (أي يتغاضى عن الكارثة [التنويم المغناطيسي + الفتحة]-خطأ مطبعي :))
هل يمكن كتابة هذا الاختبار بشكل أفضل؟ أم أن هناك شيء يجب أن أعرفه؟ شكرًا جزيلاً.
المحلول
أعتقد أنك ربما تسيء تفسير الغرض من أساليب.
إنه يتحقق من أن الطريقة المحددة تم استدعاؤها بالقيمة المتوقعة.
في الصفحة 187 من كتاب ستيف يقوللاحظ كيفية استخدام طريقة MoQs .Verify () للتأكد من أن Admincontroller قام بالفعل بتسمية الحذف () مع المعلمة الصحيحة.'
لذلك في حالتك ، يمر الاختبار لأنه مجرد التحقق من المكالمة وليس الوظيفة.
كما يتم اتباع TDD أثناء الكتاب إضافة
productsRepository.DeleteProduct(product);
يجب أولاً إضافة الاختبار
// Assert: Saved product to repository, then deleted and redirected
mockRepos.Verify(x => x.SaveProduct(newProduct))
mockRepos.Verify(x => x.DeleteProduct(newProduct));
Assert.AreEqual("Index", result.RouteValues["action"]);
ثم أضيفت إلى الكود
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Product product, HttpPostedFileBase image)
{
...
productsRepository.SaveProduct(product);
productsRepository.DeleteProduct(product);
...
نصائح أخرى
كما قال آخرون ، يمر الاختبار لأن تأكيدك:
mockRepos.Verify(x => x.SaveProduct(newProduct));
تم الوفاء به. الكود الخاص بك فعل استدعاء طريقة SaveProduct.
لا يمكن أن تتحقق طريقة mock.verify () من أن طريقة أخرى لم يكن ودعا ، وهو ما تتوقع أن تفعله.
إذا كنت قلقًا بشأن شيء غريب يحدث (مثل حذف () يتم استدعاؤه بعد حفظ ()) وتريد منعه من خلال اختبار ، يجب عليك إضافة التحقق () لهذا الشرط أيضًا. شيء مثل:
mockRepos.Verify(x => x.DeleteProduct(newProduct), Times.Never());
"إفساد" الكود المتعمد لا يكسر الاختبار كما فعلت بعد المكالمة التي لك Verify()
ل SaveProduct()
. لقد وجدت دائمًا MOQ Verify()
موثوق جدا.
قد يكون بعض رمز psuedo لاختبار أكثر قوة هو أن يكون مستودعك ينفذ واجهة ولديه إصدار بسيط في الذاكرة
// Arrange
var repo = SetupTestableRepository()
var product = CreateProduct(productId)
// Act
repo.SaveProduct(product)
// Assert
Assert.IsNotNull(repo.Fetch(productId))
العطف،
دان
الفكرة هي "كتابة أبسط رمز يعمل". يساعدك هذا على تجنب القيام بأشياء غبية مثل حذف الملفات من القرص على عملية زيادة في العداد. من الواضح ، عدم حذف الملفات أبسط.