Mocking
برای mocking از Mockall که یک کتابخانه محبوب بوده استفاده شده است. برای استفاده از traitها، باید کد خود را مجدداً تغییر دهید، سپس میتوانید به سرعت آنها را mock کنید:
use std::time::Duration;
#[mockall::automock]
pub trait Pet {
fn is_hungry(&self, since_last_meal: Duration) -> bool;
}
#[test]
fn test_robot_dog() {
let mut mock_dog = MockPet::new();
mock_dog.expect_is_hungry().return_const(true);
assert_eq!(mock_dog.is_hungry(Duration::from_secs(10)), true);
}
-
Mockall کتابخانه mocking توصیه شده در Android (AOSP) است. کتابخانههای mocking دیگری در crates.io در دسترس هستند، بهویژه در زمینه سرویسهای mocking HTTP. سایر کتابخانههای mocking به روشی مشابه Mockall کار میکنند، به این معنی که اجرای ساختگی یا mock یک ویژگی خاص را آسان میکنند.
-
توجه داشته باشید که mocking تا حدودی جنجال_برانگیز است: mockها به شما این امکان را میدهند که آزمون را کاملاً از وابستگیهای آن جدا کنید. نتیجه فوری آن، اجرای سریعتر و پایدارتر تست است. از طرف دیگر، mockها را می توان به اشتباه پیکربندی کرد و خروجی متفاوتی با آنچه وابستگی های واقعی انجام می دادند را برگرداند.
If at all possible, it is recommended that you use the real dependencies. As an example, many databases allow you to configure an in-memory backend. This means that you get the correct behavior in your tests, plus they are fast and will automatically clean up after themselves.
بهطور مشابه، بسیاری از frameworkهای وب به شما اجازه میدهند یک سرور در یک process دیگر راهاندازی کنید که به یک پورت تصادفی در
localhost
متصل میشود. همیشه این را به mock کردن framework ترجیح دهید زیرا به شما کمک میکند کد خود را در محیط واقعی آزمایش کنید. -
Mockall بخشی از Rust Playground نیست، بنابراین باید این مثال را در یک محیط local اجرا کنید. از
cargo add mockall
برای اضافه کردن سریع Mockall به پروژه Cargo موجود استفاده کنید. -
Mockall عملکرد بسیار بیشتری دارد. به ویژه، میتوانید انتظاراتی را تنظیم کنید که به استدلال های ارائه شده بستگی دارد. در اینجا ما از این برای mock کردن عملکرد cat استفاده میکنیم که 3 ساعت پس از آخرین باری که به آن غذا داده شده گرسنه میشود:
#[test]
fn test_robot_cat() {
let mut mock_cat = MockPet::new();
mock_cat
.expect_is_hungry()
.with(mockall::predicate::gt(Duration::from_secs(3 * 3600)))
.return_const(true);
mock_cat.expect_is_hungry().return_const(false);
assert_eq!(mock_cat.is_hungry(Duration::from_secs(1 * 3600)), false);
assert_eq!(mock_cat.is_hungry(Duration::from_secs(5 * 3600)), true);
}
- میتوانید از
.times(n)
برای محدودکردن تعداد دفعاتی که یک mock method میتواند بهn
فراخوانی شود استفاده کنید --- در صورت عدم ارضای این روش، زمانی که آن را حذف کنید بهطور خودکار دچار panic میشود.