امروز هم توسعه برنامه فروشگاهی که به روش TDD نوشتیم را با نگاهی نزدیک‌تر به سرویس Order Fulfillment که یک سرویس خارج از برنامه اصلی است، ادامه می‌دهیم.

ارسال سفارش

اگر نوشته قبلی را خوانده باشید، به یاد دارید که ما با یک سرویس خارج از برنامه اصلی برای اجرای سفارشات کار می‌کردیم. آن‌ها یک API فراهم کرده‌اند و ما OrderFulfillmentService را فراخوانی می‌کنیم. interface این API چندین فراخوانی و مجموعه‌ای از قوانین برای ترتیب فراخوانی‌ها دارد. خلاصه‌ای از این interface را در کد زیر می‌توانید ببینید:

می‌توانیم درباره کارآیی این interface بحث کنیم، اما به هر حال این interface ای است که شریک اجرایی ما از آن استفاده می‌کند و بنابراین ما هم باید از همین interface استفاده کنیم. چند قانون پیرامون گردش کار این API وجود دارد:

چند قید (constraint) در این قوانین وجود دارد که باید روی آن‌ها کار کنیم. در نوشته امروز به همه آن‌ها نخواهیم پرداخت، اما روی ترتیب عملیات مربوط به این قیدها کار خواهم کرد. اولین چیزی که نیاز داریم یک تست کیس (test case) است

وقتی که سفارشی ثبت می‌شود که در انبار موجود است، گردش کار اجرای سفارش باید کامل شود

درست است. این یک تست کیس بسیار ساده است. این تست روی هدف نوشته امروز بسیار متمرکز شده، که در واقع اطمینان از این مطلب است که فراخوانی‌های OrderFulfillment به ترتیب انجام شوند.

این‌ها موارد ابتدایی فراخوانی PlaceOrder در OrderService هستند همانطور که در نوشته قبلی اشاره کردم، باید برای دریافت اطلاعات مشتری (از جمله آدرس وی) CustomerService را فراخوانی کنم. حالا به arrange کردن mock نیازمندم. تغییر کوچکی در arrange فعلی انجام می‌دهم و بخش Act را با فراخوانی متد PlaceOrder از OrderService می‌سازم.

بیشتر کدی که نوشتم باید واضح باشد. در خط ۱۰ ، مقداری جهت ایجاد و گرفتن session id مربوط به تکمیل سفارش اضافه کردم و در خط ۲۲ اجرای صحیح mock را assert کردم. نکته جالب این کد در خط ۱۶ است که ثابت InOrder را اضافه کردم. بخش arrange کد را تکمیل می‌کنیم:

در کد بالا، در خط‌های ۱۴ تا ۲۶ من mock برای OrderFulfillmentService را arrange می‌کنم. نگران نباشید و حواستان با لیست پارامترهای mock پرت نشود، با ایجاد سفارشی این پارامترها در نوشته بعدی آشنا خواهیم شد. الان فقط روی ترتیب متدها متمرکز می‌شویم. متوجه شدید که mock ها را به ترتیبی که می‌خواهم متدها اجرا شوند arrange کرده‌ام. OpenSession –> IsInInventory –> PlaceOrder –> CloseSession اگر برای فراخوانی این‌ها به ترتیب دیگری عمل کنم، تست من موقع فراخوانی MockAssert حتماً fail خواهد شد.

اگر برای اجرای این تست تلاش کنم، خطای کامپایلر برای عدم تعریف _orderFulfillmentService دریافت می‌کنم. تا اینجای کار به سرویس OrdeFulfillment نیازی نداشتم ولی حالا به mock نیاز دارم:

بسیار خب. نوبت اجرای تست رسیده

تست ما fail شد چرا که هیچیک از متدهای OrderFulfillmentService  فراخوانی نشده‌اند. قدم بعدی، پیاده‌سازی کد برای این تست است

در خط ۱۴ شروع کردم به کار با OrderFulFillmentService و برای اینکه بدانیم در هر مرحله چه کاری انجام می‌شود در کد، توضیح (comment) گذاشته‌ام. حالا توجه کنید که گام‌های فراخوانی من به ترتیب مورد انتظار نیست. من از باز کردن session مستقیماً به سفارش می‌روم به جای اینکه اول موجودی انبار را چک کنم. می‌توانم تلاش کنم تست را اجرا کنم ولی به دلیل نبود وهله (instance) از OrderFulfillmentService خطای کامپایل دریافت می‌کنم، همچنین سازنده کلاس را برای تزریق وابستگی به روز نکرده‌ام. حالا این دو مشکل را حل می‌کنم. در حالی که در مشغول این کار هستم، ثابت‌های نام کاربری و کلمه عبور را هم تعریف می‌کنم

تلاش برای اجرای کد، به خطاهای کامپایل بیشتری منجر می‌شود چرا که تست من برای تزریق mock مربوط به OrderFulFillmentService  به عنوان سومین آرگومان OrderService به روز نشده. این به روز رسانی را هم انجام می‌دهم

برنامه در نهایت کامایل می‌شود. حالا نوبت اجرای تست است و مجدداً fail می‌شود!

این نتیجه غیرمنتظره نبود، اگر به یاد داشته باشید به عمد متدها را با ترتیب غیرصحیحی در OrderFulfillmentService فراخوانی کردم. نرم‌افزار (در این سری نوشته‌ها JustMock) به ما می‌گوید که ترتیب فراخوانی متدها صحیح نیست و لیست ترتیب فراخوانی را هم نشان می‌دهد. با جابجایی فراخوانی متدها به کد زیر می‌رسیم:

نوبت اجرای مجدد تست است.

با اطمینان یافتن از اینکه متدها با ترتیب درستی فراخوانی می‌شوند، می‌توانم مطمئن شوم که تستم pass خواهد شد.

ادامه دارد …