‫تجاربی از CI و Automatic Unit Testing با TeamCity

به سلامتی TeamCity را به قصد راه اندازی CI و انجام خودکار Unit Testها راه انداختیم اما مشکلات و مسائل زیادی به وجود آمد. بعضی‌ها حل شدند و بعضی‌ها نه. خلاصه‌ای از نکاتی که به آن برخورد کردم:

۱- نصب خود TeamCity خیلی ساده و سریع بود. ولی تا آنجا که فهمیدم فقط با MSBuild می‌شود با آن کار کرد و مثل TFS نیست که بشود با WorkFlow آن کارهای اضافی کرد.

۲- با آن که از git استفاده می‌کنیم ولی خوشبختانه مسائل ارتباط با git خیلی خیلی کمتر از آنی بود که فکر می‌کردم. حتی بخش CI که بایستی با push کردن هر تغییر تریگر شود بدون کمترین مشکلی کار کرد (اقلاً مشکل خاصی حس نکردم).

۳- معرفی Build Agentها به دلایلی مثل روشن بودن فایروال، نبودن git در مسیر اجرایی ویندوز و غیره اذیت کرد ولی نه خیلی.

۴- مشکل NuGet فوق‌العاده شدید بود. به راحتی آب خوردن یکی دو روز از وقتم را گرفت. با آن که تنظیم کرده بودم که دریافت packageها خودکار باشد ولی TeamCity با آن که packageها را دریافت می‌کرد باز هم build error می‌داد. به عنوان یک راه حل موقتی فایل‌های packageها را دستی در Build Agentها کپی کردم. ولی بعد از کش و قوس‌های فراوان تصمیم گرفتم NuGet را کنار بگذارم و همه Assemblyها مورد نیاز در داخل سورس کنترل اضافه کنم.

۵- مشکل بعدی مربوط به build target در یکی از Agentها بود. اول فکر کردم مشکل به خاطر نصب نبودن MVC 3 (پروژه مورد استفاده ما MVC 3 است) در agent است. اما متوجه شدم آنجام MVC 3 نصب هست و احتمالا مشکل از نصب نبودن Visual Studio 2010 در آنجا است. به هر صورت تصمیم گرفتم کمی کثیف کاری کنم (راه بهتری پیدا نکردم) و فایل ‎.targets مربوطه به agent مشکل دار کپی کنم.

۶- قدم بعدی انجام اتوماتیک Unit Testها بود. تنظیم آن محدود به یک Build Step ساده بود ولی در اولین قدم معرفی اسمبلی حاوی test کمی مشکل ایجاد کرد که با کمی سعی و خطا حل شد. اگر ساختار فولدر پروژه عوض شود باید آن را هم به روز رسانی کنم.

۷- مشکل Unit Test محدود به مشکل قبلی نبود. در یکی Agentها که ۶۴ بیتی بود، Unit Testها Run نمی‌شدند. در Unit Testهای مورد اشاره، عملیات دیتابیسی با استفاده دیتابیس داخل حافظه‌ای SQLite تست می‌شد. یادم آمد که SQLite دو نسخه مجزا برای محیط‌های ۳۲ بیتی و ۶۴ بیتی دارد. باید راهی پیدا می‌کردم تا Testها هم در ماشین ۳۲ بیتی اجرا شوند و هم در ماشین ۶۴ بیتی. تازه ماشین‌های development هم همگی ۳۲ بیت بودند و نباید یکپارچگی را از دست می‌دادم. مناسب‌ترین راه حل این بود که در زمان اجرا (Run Time) تشخیص می‌دادم که محیط ۳۲ یا ۶۴ بیتی است و بعد اسمبلی متناظر را به application اضافه می‌کردم. این راه زیادی Low Level بود. یک راه دیگر استفاده از GAC بود. اما من نهایتاً یک راه ساده و کثیف را (اقلا موقتی) انتخاب کردم. نسخه ۶۴ بیتی SQLite را دستی در فولدر Work (مسیر خاص پروژه من) کپی کردم و مشکل حل شد. حالا کل سیستم ۳۲ بیت بود ولی آن Agent خاص برای انجام Unit Testها از نسخه ۶۴ بیت خودش استفاده می‌کرد.

‫‫‫Database Unit Testing در Sharp Arch.‎

یکی از روش‌های رایج در Unit Test کدهای مربوط به دیتابیس این است که یک دیتابیس داخل حافظه‌ای ساخته شده و همه تست‌ها روی آن انجام شود. در پروژه‌های NHibernate این کار معمولا طی مراحل زیر انجام می‌شود:

۱- انجام تنظیمات دیتابیس Sqlite به صورت داخل حافظه‌ای
۲- ایجاد خودکار دیتابیس از روی mappingها در مرحله Setup تست واحد
۳- ایجاد/تزریق داده‌های امتحانی مورد نیاز در ادامه مرحله قبل
۴- انجام unit test مورد نظر

در پروژه‌های قبلی، مرحله ایجاد دیتابیس و تنظیمات session را به طور کاملا دستی انجام می‌دادیم اما از وقتی که از Sharp Arch. استفاده می‌کنیم می‌توان از روش‌های ساده‌تری استفاده کرد. مراحل انجام کار:

۱- ایجاد ارجاع به SharpArch.Tests
۲- ارث بری همه testها از RepositoryTestsBase
۳- initialization اولیه Service Locator در Setup تست
۴- انجام تست‌های مورد نظر

یک نمونه تست را در ادامه می‌بینیم:

using ProjectName.Domain;
using ProjectName.Domain.Contracts.Tasks;
using ProjectName.Infrastructure.Repositories;
using ProjectName.Tasks;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using CommonServiceLocator.WindsorAdapter;
using Microsoft.Practices.ServiceLocation;
using NUnit.Framework;
using SharpArch.Domain.PersistenceSupport;
using SharpArch.NHibernate;
using SharpArch.Testing.NUnit.NHibernate;

namespace ProjectName.Tests
{
[TestFixture]
public class SimpleEntityTaskTest : RepositoryTestsBase
{
private readonly ISimpleEntityTask _simpleEntityTask;

public SimpleEntityTaskTest(ISimpleEntityTask simpleEntityTask)
{
_simpleEntityTask = simpleEntityTask;
}

[SetUp]
protected override void SetUp()
{
ServiceLocatorInitializer.Init();
base.SetUp();
}

protected override void LoadTestData()
{
//load test data
}

[Test]
public void FindAll()
{
Assert.AreEqual(0, _simpleEntityTask.FindAll().Count);
}
}
}

‫Mocking با استفاده از Moq

Mocking روشی در Unit Test است که با کمک آن رفتار کلاس‌ها و آبجکت‌هایی که وابسته به منابع بیرونی بوده و غیر قابل کنترل هستند سنجیده می‌شود. منظور از آبجکت‌های غیر قابل کنترل، آبجکتی‌های مثل DateTime.Now در دات‌نت، کلاس‌های load اطلاعات از دیتابیس، کلاس‌های کار با deviceهای بیرونی مثل شبکه و فاکس و غیره می‌باشد. همان طور که می‌دانید این طور کلاس‌ها را نمی‌توان با کمک Unit Test مورد آزمایش قرار داد.

یکی از معروف‌ترین ابزارهایی که برای این کار وجود داشت Rhino Mocks بود. یک سال و خورده‌ای پیش سعی کردم از این کتابخانه در Unit Testهایم استفاده کنم. اما به دلیل آن که استفاده از این کتابخانه و فهم آن برایم سخت بود زیاد نتوانستم از آن استفاده کنم. البته نیاز به آن Unit Testها هم کم شده بود و نهایتاً mocking به فراموشی سپرده شد. طی چند روز گذشته که داشتم چند unit test جدید به کارویس اضافه می‌کردم باز هم نیاز به mocking پیدا کردم. نگران بودم که چطور باید با روش پیچیده Rhino Mocks کنار بیام. حدس زدم طی این یکی دو سال Rhino Mocks پیشرفت زیادی کرده و راحت‌تر شده یا این که اقلاً یا منابع یادگیری اون بیشتر شده یا شاید هم frameworkهای mocking جدیدی به وجود آمده‌اند.

با یک search در گوگل فهمیدم حدسم اشتباه نبوده است. کتابخانه جدیدی به اسم Moq وارد عرصه رقابت Mocking شده که خیلی راحت‌تر از Rhino Mocks است. Moq کاملاً بر اساس امکانات C# 3.5 نوشته شده و به همین علت می‌توان به راحتی با Lambda Expression با آن کار کرد. به مثالی که در همان صفحه معرفی Moq آمده دقت کنید تا متوجه سادگی آن شوید. البته Rhino Mocks هم امکان کار با Lambda Expression را دارد اما باز هم به نظر من Moq راحت‌تر و ساده‌تر است. برای مقایسه بین Moq و بقیه فریمورک‌ها به این نوشته اسکات هنزلمن مراجعه کنید. برای کسب اطلاعات بیشتر راجع به mocking و Rhino Mocks به این و این نوشته هم مراجعه کنید.

تمرین تغییر مداوم و تست واحد

یکی از مهم‌ترین جنبه‌های روش‌های جدید مبتنی بر agile توسعه نرم‌افزار بر اساس نیاز محدود فعلی و تغییرات مداوم آن بر اساس تغییر نیازمندی‌های مشتری یا تغییر درک تیم از نیازمندی‌هاست. روش‌های جدید به ما می‌گویند هیچ چیزی را از همان اول به طور کامل نسازیم. اول یک تیکه کوچک از آن را به طور کامل بسازیم و بعداً در صورت نیاز آن را تغییر دهیم.

تغییرات مداوم نرم‌افزار از آن چیزهایی است که برنامه‌نویس‌ها همیشه از آن گریزان بوده و آن را سخت می‌دانند. این سختی چیزی است که نمی‌توان از آن فرار کرد. برای زنده ماندن در دنیای پر تغییر و پر رقابت امروز باید به این سختی تن داده و به تغییر مداوم نرم‌افزار عادت کرد.

در همین راستا سعی کردم تغییر مداوم را در پروژه «کارویس» تمرین کنم. باید اذعان کنم آنقدرها هم سخت نبود. در واقع تغییر مداوم چیزی است که می‌توان تا اندازه‌ای به آن عادت کرد. یعنی اگر شما به این دیدگاه عادت کنید خود به خود در برنامه‌هایی که می‌نویسید موارد لازم را تا انداره‌ای رعایت خواهید کرد. خوشبختانه پیروی از الگوی تغییر مداوم در صورتی که اصولی انجام شود باعث افزایش سرعت در پیاده‌سازی تیکه تیکه‌های نرم‌افزار هم می‌شود.

یکی از موضوعاتی که سعی کردم در کنار «تغییر مداوم» تمرین کنم، انجام تست واحد (unit test) بود. باید صادق بوده و اعتراف کنم که متاسفانه در این زمینه تا این لحظه هیچ موفقیتی به دست نیاورده‌ام. انجام این کار سخت‌تر از آنی بود که فکر می‌کردم. به خاطر ماهیت «کارویس» نیاز به mocking زیادی بود که وقت آن را نداشتم. علاوه بر این در خیلی از موارد طراحی تست سخت‌تر از پیاده‌سازی آن بود. وسوسه شیطانی اختصاص وقت تست به توسعه را هم می‌توانید به فهرست دلایل اضافه کنید. هنوز هم در حال تلاش برای عادت کردن به unit testهای موثر در کارویس و دیگر پروژه‌ها هستم.

Unit tests and DRY

One of common things that I unit test with NUnit is testing throwing or not throwing a specific exception. This is done using Assert.Throws and Assert.DoesNotThrow. I used to write 2 method for a exception assert unit test. One that do the actual work and one for unit test previous method. Consider following:

pubic void method1()
{
int a =1;
int b=2;
//plenty setup needed here

MyClass.DoSomething(a, b);
}

[Test]
public void DoSomethingTest()
{
Assert.DoesNotThrow(method1);
}

Now suppose that you have to unit test MyClass.DoSomething against many similar inputs. One way to do is repeat method1 and DoSomethingTest as needed. A disadvantage is that it’s against DRY principle. As Assert.DoesNotThrow ony accepts methods that has not parameter, I couldn’t stop to repeat initialization/setup codes in every method.

Fortunately today I found that I can use Anonymous Methods with Assert.Throws and Assert.DoesNotThrow without need to create several methods. Using this way DRY is leveraged in unit tests. See following example:

[Test]
public void DoSomethingTest()
{
int a1 = 1;
int b1 =2;

int b2 =4;

int b3 = -1;

Assert.DoesNotThrows(delegate()
{
MyClass.DoSomething(a1, b1);
});

Assert.DoesNotThrows(delegate()
{
MyClass.DoSomething(a1, b2);
});

Assert.DoesNotThrows(delegate()
{
MyClass.DoSomething(a1, b3);
});

Note: Many others have problems with applying DRY or KISS with unit tests including this one.

مشکل ارتقای اجزای نرم‌افزار

یکی از مشکلات بزرگی که نرم‌افزار نویس‌ها مدام با آن دسته و پنجه نرم می‌کنند مشکل ارتقا اجزا و بخش‌های مختلف یک نرم‌افزار است. برای این مشکل مثال‌های زیادی وجود دارند:
۱- برنامه را با VB6 نوشته‌اید ولی حالا که به VB.NET ارتقا داده‌اید متوجه شده‌اید که پیش‌فرض VB.NET برای اعضای کلاس private است نه public.
۲- برنامه را با NHibernate 1.2 نوشته‌اید ولی بعد از ارتقا به NHibernate 2.0 فهمیده‌اید که برنامه با آن configuration قدیمی کار نمی‌کند و باید web.config/app.config را هم عوض کنید.
۳- برنامه را با فلان library نوشته‌اید و بعد از ارتقا به نسخه جدید فهمیده‌اید که نسخه جدید به خیلی از مسائلی که قبلاً گیر نمی‌داد حالا گیر می‌دهد و نمی‌گذارد برنامه اجرا شود.
۴- در برنامه‌های ASP.NET از کنترل‌های Telerik استفاده کرده‌اید و بعد از ارتقا فهمیدید که tagهای استفاده شده در markup اسمشان عوض شده و حالا دچار parser error شده‌اید.
۵- در برنامه‌ای که برای ویندوز ۹۵ نوشته شده از یک API خاص استفاده شده که دیگر در ویندوزهای جدیدتر وجود ندارد.
۶- در بخشی از برنامه از نسخه x یک library استفاده کرده‌اید و بعداً لازم می‌شود بخشی از یک نرم‌افزار دیگر را به نرم‌افزار فعلی‌تان الحاق کنید اما این بخش جدید از نسخه y استفاده می‌کند نه x.
۷-…

این مسئله که برای برنامه‌نویسان عذاب‌آور و برای مدیران ترس‌آور است را می‌توان به دو بخش خارجی و داخلی تقسیم کرد. بخش خارجی مربوط است به dllها، libraryها، APIها و platformهایی که از خارج شرکت/تیم می‌آیند و معمولاً حق انتخاب زیادی در مورد آنها وجود ندارد. بخش داخلی مربوط است به اجزا و dllهایی که در داخل شرکت ساخته می‌شود و version زدن آنها یک مصیبت بزرگ است. در مورد dllهای داخلی مسئله backward comaptiblity و وابستگی به dllهای دیگر هم باید چک شود. چیزی که معمولاً در مورد dllهای خارجی بهتر رعایت می‌شود.

برای کاهش مشکلات ارتقا به نظر بنده موارد زیر را می‌توان در نظر گرفت:
۱- مثبت‌نگر باشید. ارتقا dllها خصوصاً در مورد dllهای خارجی معمولاً نوید دهنده امکانات بهتر و کامل‌تر است. معمولاً هدف از ارائه نسخه جدیدتر رفع اشکالات نسخ قبلی، بهبود عملکرد و… است. پس بنابراین خوشحال باشید که رفع مشکلات مربوط به نسخه جدید به معنی ارتقا کیفیت نرم‌افزار شما خواهد بود.
۲- پیروی از اصل KISS (Keep It Simple Stupid)‎: یعنی تا آنجا که می‌توانید برنامه را ساده نگه داشته و بیخودی از هر کتابخانه، class و dll دیگری استفاده نکنید.
۳- Dependency Injection: برنامه‌ها با حداقل وابستگی به هم نوشته شوند.
۴- موتوا قبل ان تموتوا (بمیرید قبل از آن که بمیرید): قبل از آن که مجبور شوید ارتقا دهید، ارتقا دهید. تولید کنندگان نرم‌افزار معمولاً قبل از ارائه نهایی نسخ جدید آنها را به صورت نسخه‌های آزمایشی ارائه می‌دهند و حتی قبل از آن کلی بحث راه می‌اندازند، نظر سنجی و اطلاع‌رسانی می‌کنند که ما قرار است فلان چیز را به نرم‌افزارمان اضافه کنیم یا تغییر بدهیم. بنابراین فرصت خیلی زیادی دارید که خود را به موقع ارتقا دهید.
۵- پیروی از تجارب TDD مثل Unit Test و Continuous integration: این راه‌حل خصوصاً در مورد dllهای داخلی خیلی خوب جواب می‌دهد. اگر برای همه بخش‌هایی ممکن unit test نوشته باشید آن وقت نگرانی کمتری برای ارتقا دارید چون خیلی سریع می‌فهیمد که آیا چیزی خراب شده یا نه. Continuous integration هم به همین شکل کمک می‌کند که در حداقل زمان ممکن خطا را کشف کنید.
۶- به هیچ وجه Warningهای هنگام کامپایل را دستکم نگیرید. خیلی از warningهای نسخه امروز به compile errorهای نسخه فردا تبدیل خواهند شد.
۷- استفاده از الگوهای جدیدی مثل MVC چون کار تست را راحت‌تر کرده و decoupling که با استفاده از dependency injection محقق می‌شود را بهتر اجرا می‌کنند.

شما چه راه‌هایی برای کاهش این طور مشکلات سراغ دارید؟

‫Mocking و Rhino Mocks

از همان اولین باری که اسم Mock و Mocking را شنیدم حس کردم چیز گنگی است و تا لازم نشده سراغ آن نروم. اما به تازگی فهمیدم که اولاً با Mocking بعضی unit testهای غیر ممکن، ممکن می‌شوند، ثانیاً استفاده از آن می‌تواند تست نرم‌افزار را خیلی راحت‌تر و شیرین‌تر کند. قاعدتاً همه اسم Mocking را شنیده‌اند و تا حدودی می‌دانند به چه در می‌خورد و حتی شاید مثال‌هایی را از آن دیده باشند. اگر واقعاً چیزی از آن نمی‌دانید به این مطلب و این مطلب از وحید مراجعه کنید.

مشکل من با Mocking از آنجا بود که نمی‌دانستم از کجا باید شروع کنم و چه چیزی را باید یاد بگیرم. من تمام وبلاگ/سایت نویسنده Rhino Mocks که تبدیل به استانداردی در دنیای Mocking شده را زیر و رو کردم، همینطور StackOverflow و گوگل را. اما ظاهراً خیلی از مطالبی که پیدا می‌کردم از جمله مطالب خود وبلاگ/سایت نویسنده آن یعنی Ayende Rahien از تاریخ گذشته و اصطلاحاً depricate شده بودند یا این که فهمیدن آنها خیلی سخت بود. هر کسی از هر روشی که خوشش آمده بود استفاده کرده بود و هیچ منبع درست و حسابی پیدا نمی‌شد. خوشبختانه با همه بالا و پایین‌ها متوجه شدم که دو روش کلی برای انجام Mocking با Rhino Mocks وجود دارد:

۱- روش کلاسیک یا Record-Replay: این روش قدیمی‌تر است و مبتنی بر انجام یک سری عملیات پشت سر هم، ضبط و سپس تکرار آنهاست. بیشتر منابعی که در اینترنت پیدا کرده بودم از این روش استفاده می‌کردند.

۲- روش AAA: این روش بعد از ورود lambda expressionها و extension methodها به C#‎ ابداع و مورد استفاده قرار گرفته است. بیشتر افراد معتقد هستند این روش خیلی راحت‌تر و خواناتر است. من هم این روش را برای ادامه کارم انتخاب کرده‌ام. یک مطلب بسیار خوب در مورد یادگیری این روش در اینجا آمده است.

برای استفاده از Mocking در تست‌ها باید آماده برداشتن یک قدم مهم بود: استفاده از مفاهیم Decoupling و Dependency Injection در سطح کد یا حداقل استفاده از کلاس‌های Virtual و غیر Static. چون Rhino Mock و بقیه ابزارها یا فقط از interfaceها یا از کلاس‌هایی که متودشان به صورت virtual تعریف شده باشد می‌توانند استفاده کنند. دلیل آن هم اصلاً غیر منطقی نیست. به یاد داشته باشید برای استفاده از Lazy Loading در NHibernate هم باید setterها و getterها به صورت Virtual تعریف می‌شد.

چند منبع:
۱-  مطلب اول و دوم وحید
۲- صفحه‌ی رسمی Rhino Mocks
۳- وبلاگ پدیدآورنده‌ی Rhino Mocks
۴- نوشته‌ی مارتین فولر درباره فرق Stub و Mock
۵- راهنمای خیلی خوبی برای شروع Mocking با استفاده از روش AAA
۶- صفحه‌ی ویکی‌پدیا درباره‌ی Mocking
۷- توضیحات پدیدآورنده‌ی Rhino Mocks درباره روش AAA

‫کمی درباره‌ی Mock و Stub

هم Mock و هم Stub در unit testهایی استفاده می‌شوند که شخص نمی‌تواند یا نمی‌خواهد از بعضی objectهای مورد نیاز استفاده نماید. مثلاً قرار است متود ارسال ایمیل به امور فروش در صورت کاهش موجودی برخی کالاها تست شود. فرض کنید موقع تست امکان ارسال ایمیل به علت قطعی اینترنت وجود ندارد. در این حالت آبجکت مربوط به ارسال ایمیل به نوعی شبیه‌سازی می‌شود. این کار باعث می‌شود تست مورد نظر روی خود عملیات کاهش موجودی و ارسال ایمیل تمرکز کند و کاری به مشکلات مربوط به ارسال ایمیل نداشته باشد. به غیر از ارسال ایمیل حالات دیگری هم وجود دارند که در آن استفاده از object مورد نظر امکان‌پذیر نیست. مثلاً خواندن اطلاعات از یک device وقتی که خود device را نداریم، محاسبه حقوق بر اساس اطلاعات کارمندان یک شرکت وقتی که اطلاعات هیچ کدام از کارمندان را نداریم و بسیاری حالات دیگر. خود شبیه‌سازی هم صرفاً محدود به Mock و Stub نمی‌شود. مثلاً می‌توان از الگوهایی مثل Object Mother هم استفاده کرد.

Mock با استفاده از برنامه‌های کمکی که به اسم Isolation Framework یا Mocking Framework معروف هستند انجام می‌شود. Rhino Mocks معروف‌ترین و پراستفاده‌ترین Mock Framework در دات‌نت است. در روش Mock ما آن آبجکتی را که قرار است شبیه‌سازی شود را معرفی می‌کنیم و سپس انتظاراتمان را از آن بیان می‌کنیم. مثلاً فرض کنید آبجکتی به اسم FaxReceiver دارید که یکی از متودهایش وظیفه دارد به شما بگوید از تاریخ آخرین عوض کردن کاغذ دستگاه فاکس، چند عدد فاکس دریافت کرده است. متود مورد تست شما از این آبجکت استفاده می‌کند و هر وقت که تعداد فاکس‌های دریافتی بیش از هزار عدد شد به اپراتور دستگاه پیغام دهد که موقع عوض کردن کاغذ دستگاه فرا رسیده است. با روش‌های معمولی تست نمی‌توان این متود را تست کرد مگر این که هزار عدد فاکس دریافت کنید. در اینجاست که از روش‌های شبیه‌سازی مثل Mock استفاده می‌شود. برای این کار آبجکت FaxReceiver به Mock Framework معرفی شده و به او می‌گوییم هر وقت متود تعداد فاکس‌های دریافتی فراخوانی شد از او «انتظار» داریم مقدار هزار را برگرداند.

مثال بالا را می‌توان با Stub هم انجام داد. با این تفاوت که در مورد Stub هیچ Framework یا Library وجود ندارد و شما مجبور هستید همه یا بخشی از آبجکت/متود مورد نظر را خودتان بنویسید. مثلا متودی بنویسید که به جای مراجعه واقعی به دستگاه فاکس و خواندن تعداد فاکس‌های دریافتی از آن، همیشه عدد هزار را برگرداند. با این که کار با Stub خیلی سخت‌تر از کار با Mock است ولی بعضی حالات وجود دارند که فقط با Stub می‌شود آنها را پیاده‌سازی کرد. مثلاً وقتی که نگهداشتن State برای ما مهم باشد. به عنوان مثال فرض کنید در تست دیگری بخواهیم بدانیم چند بار متود فراخوانی تعداد فاکس‌های دریافتی فراخوانی شده است. انجام این کار با Mocking امکان‌پذیر نیست و باید از روش Stub استفاده شود.

منابع:
Mocks Aren’t Stubs
Mock object
آشنايي با mocking frameworks (چارچوب‌هاي تقليد) – قسمت اول
آشنايي با mocking frameworks – قسمت دوم