Unit Testing در ASP.NET Core MVC
شناسه پست: 3373
بازدید: 2181

در این مقاله قصد داریم به بررسی Unit Testing (تست واحد) یا بهتر بگوییم چرایی نیاز به تست های واحد و نحوه پیاده سازی آنها در برنامه های ASP.NET Core بپردازیم.

اگر برخی از مقالات قبلی این آموزشی سریالی را ندیده اید، توصیه می کنیم صفحه مربوط به این سری آموزشی را مشاهده کنید: آموزش سریالی ASP.NET Core MVC.

برای دانلود سورس کد این مقاله، روی این لینک کلیک کنید: Unit Testing در ASP.NET Core MVC.

شروع کنیم.

چرا به تستهای واحد نیاز داریم؟

برنامه های ما امکان دارد به طور غیرمنتظره ای در پاسخ به تغییرات با مشکل روبه رو شوند. از این رو، تست خودکار بعد از تغییرات در تمام برنامه ها مورد نیاز است.

تست دستی، کندترین، کم اعتبارترین و گرانترین راه برای آزمایش یک برنامه است. اما اگر برنامه ها به گونه ای طراحی نشده اند که قابل تست باشند، تست دستی ممکن است تنها راه در دسترس ما باشد.

بنابراین اولین قدم این است که مطمئن شوید برنامه به گونه ای طراحی شده است که قابل آزمایش باشد. برنامه هایی که از اصول معماری خوب پیروی می کنند مانند تفکیک نگرانی ها (Separation of Concerns)، وارونگی وابستگی، مسئولیت منفرد (Single Responsibility)، خودت را تکرار نکن (DRY) و غیره به راحتی قابل آزمایش هستند. ASP.NET Core از واحد خودکار، یکپارچه سازی و تست عملکرد پشتیبانی می کند.

یک تست واحد به معنی تست یک قسمت واحد از منطق برنامه ما است. کد ما امکان دارد وابستگیهایی بر روی لایه های پایین ترو کامپوننتهای خارجی داشته باشد. اما آنها با تستهای واحد اعتبارسنجی نمیشوند. تست واحد به طور کامل در حافظه و در فرآیند اجرا می شود. با سیستم فایل، شبکه یا پایگاه داده ارتباط برقرار نمی کند.

تست های واحد فقط باید کد ما را تست کنند.

با توجه به این دلایل، تست های واحد باید بسیار سریع اجرا شوند و ما باید بتوانیم آنها را به طور مکرر اجرا کنیم. در حالت ایده‌آل، ما باید تست‌های واحد را قبل از ارسال هر تغییر به source control repository و همچنین با هر build خودکار روی build server اجرا کنیم.

راه اندازی Framework تست واحد

framework های تست زیادی در market امروزی وجود دارد. با این حال، برای این مقاله، قصد دادریم از xUnit استفاده کنیم که یک framework تست خیلی معروفی است. حتی تستهای ASP.NET Core و EF Core توسط آن نوشته شده اند.

ما میتوانیم با استفاده از xUnit Test Project template یک پروژه تست xUnit در ویژوال استودیو اضافه کنیم که در ویژوال استودیو در دسترس میباشد:

افزودن پروژه تست واحد در asp.net core

ما همیشه باید تستهای خود را به سبکی ثابت نام‌گذاری کنیم، با نام‌هایی که مشخص کند که هر تست چه کاری انجام می‌دهد. یک رویکرد خوب این است که کلاس ها و متدهای آزمایشی را با توجه به کلاس و متدی که در حال آزمایش هستند نامگذاری کنید. این کاملاً مشخص می کند که هر آزمایش چه مسئولیتی دارد.

ما می توانیم رفتاری را که در حال آزمایش است را به نام هر test method اضافه کنیم. این باید شامل رفتار مورد انتظار و هر ورودی یا فرضیه هایی باشد که باید این رفتار را نشان دهد.

بنابراین، هنگامی که یک یا چند تست با شکست مواجه می شوند، از نام آنها مشخص است که چه مواردی شکست خورده اند. ما زمانیکه تستهای واحد را در قسمت بعدی ایجاد میکنیم از این قواعد نام گذاری پیروی خواهیم کرد.

بنابراین یک NuGet package reference برای Moq اضافه کنیم که یک فریم ورک آبجکت ساختگی است. این امر، آبجکتهای آزمایشی که آبجکتهای ساختگی یا مجموعه ای از ویژگی ها و رفتارهای متد از پیش تعیین شده برای آزمایش هستند را در اختیار ما قرار می دهد.

تستهای واحد در متدهای کنترلر

بگوییم که یک EmployeeController با یک متد Index() و Add() تعریف کرده ایم:

حالا نحوه نوشتن تستهای واحد برای این اکشن متدها را بررسی کنیم. کنترلر ما از تزریق وابستگی برای گرفتن مقدار برای dataRepository_ استفاده میکند. این باعث میشود که این امکان را برای unit testing framework فراهم کند تا یک آبجکت ساختگی را ارائه داده و متد ها را تست کند.

الگوی (Arrange, Act, Assert) AAA یک شیوه ی رایج برای نوشتن تستهای واحد است و ما همین الگو را اینجا دنبال خواهیم کرد.

قسمت Arrange یک متد تست واحد، آبجکتها را مقداردهی اولیه میکند و مقادیر را برای ورودیهایی که به متد مورد آزمایش پاس داده میشوند set میکند.

قسمت Act، متد مورد آزمایش را به همراه پارامترهای Arrange فراخوانی میکند.

قسمت Assert تأیید می کند که اکشن متد مورد آزمایش، طبق انتظار عمل می کند.

آزمایش متد ()Index

حالا تستها را برای متد ()Index بنویسیم:

ما اول با استفاده از متد ()GetTestEmployees، سرویس IDataRepository<Employee> را mock کردیم. ()GetTestEmployees یک لیست از دو آبجکت ساختگی را ایجاد کرده و برمیگرداند.

سپس متد ()Index اجرا شده و موارد زیر را روی نتیجه assert میکند:

  • یک ViewResult برمیگرداند
  • نوع مدل برگشتی List<Employee> میباشد
  • دو آبجکت Employee در مدل برگشتی وجود دارد

هر test method با یک ویژگی [Fact] مزین شده است که نشان می دهد این یک متد واقعی است که باید توسط test runner اجرا شود.

آزمایش متد ()Add

حالا تستها را برای متد ()Add بنویسیم:

اولین تست تأیید می کند که زمانیکه ModelState.IsValid برابر با false است، اکشن متد یک ViewResult 400 Bad Request را با داده های مناسب برمی گرداند. می‌توانیم با اضافه کردن خطاها با استفاده از متد ()AddModelError وضعیت مدل نامعتبر را آزمایش کنیم.

تست دوم تأیید می‌کند که وقتی ModelState.IsValid برابر با true است، متد ()Add در repository  فراخوانی می‌شود و RedirectToActionResult با آرگومان‌های صحیح بازگردانده می‌شود.

متدهای Mock که ما آنها را فراخوانی نمی کنیم معمولا نادیده گرفته می شوند، اما با فراخوانی ()Verifiable همراه با تنظیمات، می توانیم تایید کنیم که متدهای Mock فراخوانی شده اند. ما می‌توانیم این را با استفاده از mockRepo.Verify تأیید کنیم، که اگر متد مورد انتظار فراخوانی نشده باشد، آزمایش مورد نظر شکست می‌خورد.

اجرای تستها

ما میتوانیم تستها را با استفاده از Test Explorer در Visual Studio اجرا کنیم:

test explorer در ویژوال استودیو

در Test Explorer می‌توانیم تمام تست‌های موجود را به‌صورت گروه‌بندی شده بر اساس Solution، Project، Class و غیره مشاهده کنیم. ما می توانیم تست ها را با اجرا یا debug کردن آن ها انتخاب و اجرا کنیم. هنگامی که تست ها را اجرا می کنیم، می توانیم یک علامت تیک سبز یا یک علامت متقاطع قرمز را در سمت چپ نام متد تست ببینیم که نشان دهنده موفقیت یا شکست در آخرین اجرای متد است. در سمت راست، می‌توانیم زمان صرف شده برای اجرای هر تست را ببینیم.

تمام. بیایید آنچه را که تاکنون یاد گرفتیم را خلاصه کنیم.

نتیجه گیری

در این مقاله، ما عناوین زیر را یاد گرفتیم:

  • دلیل نیاز به تستهای واحد در برنامه ASP.NET Core MVC
  • نحوه تنظیم تست واحد
  • نحوه تست متدهای کنترلر

در قسمت بعدی این سری آموزشی، filter ها در ASP.NET Core MVC را یاد میگیریم.

نویسنده

امید عباسی
من امید عباسی هستم. سالهاست که در زمینه برنامه نویسی با تکنولوژی دات نت فعالیت میکنم و عاشق این هستم که تجربیات و دانش خودم را در این زمینه با دیگران به اشتراک بزارم. خیلی دوست دارم که نظر و انتقاد خودتون رو در مورد این نوشته برای من بنویسید تا بتونم در آینده، مطالب بهتر و ارزشمندتری را برای شما فراهم کنم. در صورت داشتن هرگونه سوال هم در قسمت دیدگاه ها میتونید با بنده در ارتباط باشید