از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
استفاده از Mocks برای تست در جاوا اسکریپت با Sinon.jsTest "mocks" اشیایی هستند که جایگزین اشیاء واقعی می شوند در حالی که عملکرد آنها را شبیه سازی می کنند. یک mock همچنین انتظاراتی در مورد روش استفاده از توابع مورد آزمایش دارد. در برخی از موارد تست واحد ممکن است بخواهیم عملکرد جاسوس ها را ترکیب کنیم، رفتار یک روش تحت فراخوانی را مشاهده کنیم، و…
سرفصلهای مطلب
معرفی
تست “ملک” اشیایی هستند که جایگزین اشیاء واقعی در حالی که عملکرد آنها را شبیه سازی می کنند. یک mock همچنین انتظاراتی در مورد روش استفاده از توابع مورد آزمایش دارد.
در برخی از موارد تست واحد، ممکن است بخواهیم عملکرد جاسوسها را ترکیب کنیم، رفتار یک متد تحت فراخوانی را مشاهده کنیم، و رفتارهای خرد را برای جایگزینی عملکرد یک متد، در حصول اطمینان از اینکه یک فراخوانی تابع واقعی انجام نمیدهیم، اما همچنان قادر به انجام آن هستیم. بر این اساس بر رفتار عملکرد هدفمان نظارت کنیم. در چنین حالتی می توانیم از طعنه استفاده کنیم.
در این مقاله به دنبال این هستیم که بفهمیم ماک ها چیست و چگونه از آنها در آزمون های واحد استفاده کنیم. سپس دست به دست می شویم -روی تجربه با Sinon.js برای تمسخر درخواست HTTP
این مقاله سومین مجموعه ماست روی تکنیک های تست واحد با Sinon.js. توصیه می کنیم مقالات قبلی ما را مطالعه کنید روی این موضوع نیز:
- استفاده از Stubs برای تست در جاوا اسکریپت با Sinon.js
- استفاده از Spies برای تست در جاوا اسکریپت با Sinon.js
- استفاده از Mocks برای تست در جاوا اسکریپت با Sinon.js (تو اینجایی)
Mocks چیست؟
ماک ها عملکرد هر دو را ترکیب می کنند جاسوسان و خرد، به این معنی که آنها جایگزین تابع هدف می شوند اما در عین حال توانایی مشاهده روش فراخوانی تابع را در اختیار ما قرار می دهند.
علاوه بر این، مسخرهها دارای ادعاهایی هستند که انتظارات نامیده میشوند. شما انتظارات از روش استفاده از عملکرد مسخره شده خود را از قبل مشخص می کنید. اگر تمسخر شما انتظاراتش را برآورده نکرد، آزمون شما شکست خواهد خورد.
به عنوان مثال، اجازه دهید تابعی را در نظر بگیریم که با یک پایگاه داده ارتباط برقرار می کند تا جزئیات یک مخاطب را ذخیره کند. با ساختگی، به جای یک پایگاه داده واقعی، تابع ما به یک شی پایگاه داده جعلی برخورد می کند. ما می توانیم تعیین کنیم که چه نوع پاسخی خواهد داد. همچنین بیان می کنیم که پایگاه داده چند بار باید فراخوانی شود و با آرگومان هایی که باید فراخوانی شود.
در نهایت، بهعنوان بخشی از آزمایش، تأیید میکنیم که شبیهسازی پایگاه داده ما دقیقاً به تعداد دفعاتی که انتظار داشتیم نامیده میشود. همچنین بررسی میکنیم که فقط با آرگومانهایی که تابع ما قرار است آن را ارائه کند، فراخوانی شده باشد.
پس از دیدن اینکه مسخره کردن چیست، اجازه دهید اکنون به موقعیت هایی نگاه کنیم که می توانیم آنها را به کار ببریم.
چرا از Mocks استفاده کنیم؟
Mock ها هنگام تأیید روش استفاده از یک وابستگی خارجی در یک تابع مفید هستند. زمانی که به موارد زیر علاقه دارید از تملک استفاده کنید:
- تأیید اینکه وابستگی خارجی شما اصلاً استفاده شده است
- بررسی اینکه وابستگی خارجی شما به درستی استفاده شده است
- اطمینان از اینکه عملکرد شما میتواند پاسخهای مختلف از وابستگیهای خارجی را مدیریت کند.
تصور کنید که در حال آزمایش عملکردی هستید که با یک API شخص ثالث صحبت می کند تا برخی از داده های کاربر را دریافت کند. برای درخواست به API خارجی، ابتدا باید چند تماس برقرار کنید تا احراز هویت کنید. در حال حاضر استفاده از API واقعی در آزمایشات ناخوشایند شده است. علاوه بر این، ممکن است هنگام اجرای آزمایشات خود همیشه اتصال اینترنت برای دسترسی به API نداشته باشید.
با یک تمسخر، ما پاسخ های جعلی را برمی گردانیم. اکنون میتوانیم به سرعت آزمایش کنیم که عملکرد ما وقتی دادههای جعلی در قالب خاصی داده میشود، درست عمل میکند. ما همچنین می دانیم که تابع ما با پارامترهای مناسب درخواست هایی را به API ارسال می کند.
حالا بیایید ببینیم که چگونه می توانیم از Sinon.js برای ساخت mock استفاده کنیم.
استفاده از Sinon.js برای ایجاد یک Mock
ما از Sinon.js برای تمسخر پاسخ از یک API JSON که لیستی از عکسهای یک آلبوم را بازیابی میکند، استفاده میکنیم. علاوه بر Sinon.js، ما از آن استفاده خواهیم کرد موکا و چای برای راه اندازی و اجرای تست ها قبل از ادامه، می توانید راهنمای ما را بخوانید تا در مورد آنها بیشتر بدانید.
برپایی
یک دایرکتوری به نام ایجاد کنید SinonMock
و وارد آن شوید:
$ mkdir SinonMock
$ cd SinonMock
سپس از NPM برای مقداردهی اولیه پروژه برای ردیابی فایل های پروژه ای که ایجاد می کنیم استفاده می کنیم:
$ npm init -y
در مرحله بعد، ما Mocha و Chai را به عنوان وابستگی های آزمایشی برای اجرای آزمایش های خود به همراه Sinon.js نصب می کنیم:
$ npm i mocha chai sinon --save-dev
پس از تکمیل تنظیمات، اجازه دهید درخواست HTTP را مسخره کنیم.
تمسخر تماس HTTP با Sinon.js
در مقاله قبلی ما روی جاسوس های آزمایشی، ما جاسوسی کردیم روی یک درخواست HTTP به API آلبوم عکس. ما با آن مثال برای این مقاله ادامه خواهیم داد.
ایجاد یک فایل در root از SinonMock
دایرکتوری و تماس بگیرید index.js
:
$ touch index.js
در فایل ایجاد شده کد زیر را وارد کنید:
const request = require('request');
module.exports = {
getAlbumById: async function(id) {
const requestUrl = `https://jsonplaceholder.typicode.com/albums/${id}/photos؟_limit=3`;
return new Promise((resolve, reject) => {
request.get(requestUrl, (err, res, body) => {
if (err) {
return reject(err);
}
resolve(JSON.parse(body));
});
});
}
};
برای جمع بندی، getAlbumById()
تابعی است که یک JSON API را فراخوانی می کند که لیستی از عکس ها را برمی گرداند. شناسه آلبوم را به عنوان آرگومان تابع ارائه می کنیم. ما قبلا در مورد تجسس و جاسوسی تحقیق کرده ایم روی را request.get()
روش.
در حال حاضر، ما به تمسخر request
اعتراض کنید و بررسی کنید که آیا get()
متد در صورت لزوم یک بار فراخوانی می شود و بررسی کنید که آیا آرگومان های صحیح را دریافت کرده است. سپس بررسی می کنیم که تابع ما بر اساس ویژگی های صحیحی دارد روی آنچه از مسخره ما برگردانده شد
یک فایل دیگر در root از SinonMock
دایرکتوری و تماس بگیرید index.test.js
:
$ touch index.test.js
باز کن index.test.js
با یک ویرایشگر فایل کنید و کد زیر را وارد کنید:
const expect = require('chai').expect;
const request = require('request');
const sinon = require('sinon');
const index = require('./index');
describe('with mock: getPhotosByAlbumId', () => {
it('should getPhotosByAlbumId', (done) => {
let requestMock = sinon.mock(request);
const myPhotos = ({
"albumId": 1,
"id": 1,
"title": "accusamus beatae ad facilis cum similique qui sunt",
"url": "https://via.placeholder.com/600/92c952",
"thumbnailUrl": "https://via.placeholder.com/150/92c952"
},
{
"albumId": 1,
"id": 2,
"title": "reprehenderit est deserunt velit ipsam",
"url": "https://via.placeholder.com/600/771796",
"thumbnailUrl": "https://via.placeholder.com/150/771796"
},
{
"albumId": 1,
"id": 3,
"title": "officia porro iure quia iusto qui ipsa ut modi",
"url": "https://via.placeholder.com/600/24f355",
"thumbnailUrl": "https://via.placeholder.com/150/24f355"
});
requestMock.expects("get")
.once()
.withArgs('https://jsonplaceholder.typicode.com/albums/2/photos؟_limit=3')
.yields(null, null, JSON.stringify(myPhotos));
index.getAlbumById(2).then((photos) => {
expect(photos.length).to.equal(3);
photos.forEach((photo) => {
expect(photo).to.have.property('id');
expect(photo).to.have.property('title');
expect(photo).to.have.property('url');
});
requestMock.verify();
requestMock.restore();
done();
});
});
});
در مورد تست بالا، ابتدا مایکی از آن ایجاد می کنیم request
با استفاده از شی sinon.mock()
و اسمش را بگذار requestMock
. این requestMock
شی دارای عملکردهای است request
شی اما توابع به طور پیش فرض هیچ کاری انجام نمی دهند.
پس از ارائه برخی از داده های عکس ثابت، ما نسخه اصلی را لغو می کنیم get()
روش شی درخواست با استفاده از APIهای ساختگی Sinon.js expect()
روش.
این expect()
متد یک آرگومان واحد را می گیرد، که متد شیء مسخره شده ای است که پیش بینی می کنیم استفاده شود.
این once()
روش ادعا می کند که انتظارات ما یک بار فراخوانی می شود. در این مورد get()
متد شی درخواست دقیقاً یک بار فراخوانی می شود.
این withArgs()
روش ادعا می کند که ما انتظار داریم get()
روشی که باید با آرایه آرگومان هایی که به آن ارائه می کنیم فراخوانی شود. در مورد ما URL API.
این yields()
متد دادهها را در callback که شی ساختگی ما میپذیرد قرار میدهد. در این صورت خطا و پاسخ ما هر دو است null
اما بدن ما پاسخ JSON دارد.
پس از این تنظیم، ما سپس با ما تماس می گیریم getAlbumById()
روش را انجام دهید و بررسی کنید که آیا عکس ها دارای ویژگی های صحیح هستند یا خیر.
توجه کنید verify()
تماس از requestMock
مخالفت کنیم تا تأیید کنیم که انتظارات ما برآورده شده است. اگر انتظارات با شکست مواجه شوند، آزمون یک استثنا ایجاد می کند. سپس ما تماس می گیریم restore()
روشی برای دور انداختن ساختگی ایجاد شده توسط آزمایش ما و بازیابی شی درخواست اصلی.
وقتی این تست را اجرا می کنید، باید نتیجه زیر را دریافت کنید:
$ mocha index.test.js
with mock: getPhotosByAlbumId
✓ should getPhotosByAlbumId
1 passing (13ms)
✨ Done in 0.72s.
برای تأیید رفتار ساختگی خود، بیایید ببینیم اگر URL که با آن در ارتباط هستیم را تغییر دهیم، انتظارات شکست می خورد یا خیر. در شما index.js
فایل، تغییر:
const requestUrl = `https://jsonplaceholder.typicode.com/albums/${id}/photos؟_limit=3`;
به:
const requestUrl = `https://example.com`;
حالا یک بار دیگر تست ها را اجرا کنید:
$ mocha index.test.js
از آنجایی که ورودی را به the تغییر دادیم get()
روش، آرگومان URL دیگر با آنچه در آزمایش ما است مطابقت ندارد. وقتی تست را اجرا می کنیم این خروجی را دریافت خواهیم کرد:
> mocha index.test.js
with mock: getPhotosByAlbumId
(node:85434) UnhandledPromiseRejectionWarning: ExpectationError: Unexpected call: get(https://example.com, function () {})
Expected get(https://jsonplaceholder.typicode.com/albums/2/photos؟_limit=3(, ...)) once (never called)
عالی! ما کاملاً مطمئن هستیم که مسخرههای ما تضمین میکنند که عملکرد ما همانطور که انتظار داریم رفتار میکند!
با استفاده از یک ماک، ما توانسته ایم از مزایای جاسوسی و خرد بهره مند شویم. ما توانستیم بررسی کنیم که عملکرد ما دقیقاً یک بار فراخوانی شده است و با آرگومانهای صحیح، مزیتی توسط جاسوسان برای ما فراهم شد. ما همچنین میتوانستیم درخواست را قطع کنیم تا تماس HTTP واقعی با API برقرار نکنیم، که باعث میشود تست ما به سرعت اجرا شود.
نتیجه
مدلهای آزمایش واحد، عملکرد جاسوسها و خردها را با جایگزین کردن کارکردهایی مانند خرد ترکیب میکنند و در عین حال ابزارهایی برای مشاهده عملکردها برای بررسی روش فراخوانی آنها، عملکردی که توسط جاسوسان به ما ارائه میشود، در اختیار ما قرار میدهند. سپس ماک ها این مزیت را به ما می دهند که بررسی کنیم چگونه از عملکرد ما در یک آزمایش استفاده شده است.
در این مقاله مفهوم تمسخر در تست واحد را معرفی کردیم و دیدیم که چگونه می توانیم تماس HTTP را مسخره کنیم. برای کسب اطلاعات بیشتر در مورد ماک های Sinon.js، می توانید آن را مرور کنید اسناد رسمی of the mocks API.
منتشر شده در 1403-01-21 21:35:04