Robolectric — چیست، اصول کار و تست واحد Android

نویسنده: IT Sectr منتشر شده: 2026-04-09 زمان مطالعه: 8 دقیقه

Robolectric یک فریم‌ورک برای تست واحد برنامه‌های Android است که به شما امکان می‌دهد تست‌ها را مستقیماً روی JVM بدون شبیه‌ساز یا دستگاه فیزیکی اجرا کنید. این فریم‌ورک فراخوانی‌های Android SDK را رهگیری می‌کند و اشیاء shadowای را ارائه می‌دهد که رفتار کامپوننت‌های واقعی را شبیه‌سازی می‌کنند. طبق Robolectric Documentation, 2025، اشیاء shadow حدود 15 هزار کلاس Android API را جایگزین می‌کنند و ایزوله‌سازی تست‌ها از پلتفرم را تضمین می‌کنند.

نکات اصلی

  • Robolectric — فریم‌ورک تست واحد Android بدون شبیه‌ساز که روی JVM کار می‌کند
  • اشیاء shadow فراخوانی‌های Android SDK را رهگیری می‌کنند و رفتار سیستم را شبیه‌سازی می‌کنند
  • ادغام با JUnit 4 و 5 امکان استفاده از runnerهای استاندارد تست را فراهم می‌کند
  • تست‌ها در ثانیه‌ها اجرا می‌شوند، نه دقیقه‌ها مانند شبیه‌ساز
  • پشتیبانی از Jetpack Compose، fragmentها، intentها، ContentProvider و منابع

Robolectric چیست

Robolectric یک فریم‌ورک متن‌باز است که در سال 2010 برای تسریع تست برنامه‌های Android ایجاد شد. به جای اجرا روی شبیه‌ساز یا دستگاه، Robolectric پیاده‌سازی‌های shadowای از کلاس‌های Android SDK ارائه می‌دهد که مستقیماً روی ماشین مجازی Java (JVM) کار می‌کنند. این امکان اجرای هزاران تست را در ثانیه‌ها فراهم می‌کند.

مسئله‌ای که Robolectric حل می‌کند

تست سنتی Android نیاز به اجرای برنامه روی شبیه‌ساز دارد که 3–10 دقیقه برای ساخت APK، نصب و اجرا زمان می‌برد. Robolectric این مرحله را حذف می‌کند: تست‌ها به عنوان تست‌های معمولی Java/Kotlin کامپایل شده و از طریق JUnit اجرا می‌شوند. این چرخه بازخورد را در چند ثانیه به جای دقیقه‌ها فراهم می‌کند.

نسخه‌های پشتیبانی‌شده Android

Robolectric از همه نسخه‌های Android از API 16 (Android 4.1) تا آخرین نسخه پایدار پشتیبانی می‌کند. برای هر نسخه، مجموعه مربوطی از اشیاء shadow ارائه می‌شود که رفتار دقیقاً همان نسخه پلتفرمی را که برنامه روی آن تست می‌شود شبیه‌سازی می‌کنند.

معماری و اشیاء shadow

معماری Robolectric بر اساس مکانیزم رهگیری فراخوانی‌ها از طریق جایگزینی classloader است. وقتی تست متدی از Android SDK را فراخوانی می‌کند، Robolectric فراخوانی را رهگیری کرده و به شی shadow هدایت می‌کند. شی shadow یک کلاس Java است که رفتار واقعی کامپوننت Android را تقلید می‌کند اما بدون پلتفرم بومی کار می‌کند.

shadowها چگونه کار می‌کنند

اشیاء shadow متدهای کلیدی کلاس‌های اصلی Android را پیاده‌سازی می‌کنند. مثلاً ShadowTextView متدهای getText()، setText()، getCurrentTextColor() و دیگران را شبیه‌سازی می‌کند. وقتی textView.setText("Hello") فراخوانی می‌شود، shadow رشته را ذخیره کرده و هنگام فراخوانی getText() آن را برمی‌گرداند. این تست‌ها را از رندرینگ واقعی و سرویس‌های سیستم جدا می‌کند.

سلسله‌مراتب shadow

Robolectric بیش از 200 کلاس shadow را پشتیبانی می‌کند که کامپوننت‌های اصلی Android SDK را پوشش می‌دهند: Activity، Fragment، TextView، Button، RecyclerView، WebView، LocationManager، ConnectivityManager و بسیاری دیگر. اشیاء shadow از همان سلسله‌مراتب ارث‌بری کلاس‌های اصلی Android پیروی می‌کنند.

نصب و پیکربندی Robolectric

نصب Robolectric در پروژه Gradle نیاز به افزودن وابستگی testImplementation "org.robolectric:robolectric:4.x" دارد. همچنین باید پیکربندی android:sdk را در فایل build.gradle مشخص کرده و android:testInstrumentationRunner را اضافه کنید. برای کار با Robolectric پلاگین android-test مورد نیاز نیست.

پیکربندی پایه Gradle

پس از افزودن وابستگی، باید دایرکتوری را برای manifest، منابع و assets پیکربندی کنید. Robolectric به طور خودکار AndroidManifest.xml را پیدا می‌کند، اما ممکن است نیاز به مشخص کردن مسیر به صورت دستی از طریق @Config یا ویژگی‌های سیستم باشد. برای پروژه‌های چندماژولی، پیکربندی برای هر ماژول جداگانه تنظیم می‌شود.

groovy
// build.gradle — پیکربندی Robolectric
android {
    testOptions {
        unitTests.includeAndroidResources = true
        unitTests.all {
            systemProperty 'robolectric.dependency.dir',
                project.rootDir.absolutePath + '/build/intermediates'
        }
    }
}

dependencies {
    testImplementation 'org.robolectric:robolectric:4.13'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

@Config annotation

@Config امکان بازنویسی پارامترهای تست را فراهم می‌کند: sdk (نسخه API)، manifest (مسیر به manifest)، qualifiers (پیکربندی صفحه، زبان). این برای تست رفتار برنامه در نسخه‌های مختلف Android، جهت‌های صفحه و زبان‌ها مفید است.

نوشتن تست با Robolectric

تست‌های Robolectric به عنوان تست‌های واحد معمولی با @RunWith(RobolectricTestRunner.class) برای JUnit 4 یا از طریق RobolectricExtension برای JUnit 5 نوشته می‌شوند. ActivityController چرخه حیات Activity را مدیریت می‌کند: create()، start()، resume()، pause()، stop()، destroy(). این امکان تست جزئی هر انتقال حالت را فراهم می‌کند.

تست Activity

برای تست Activity از ActivityController استفاده می‌شود که به صورت ترتیبی از مراحل چرخه حیات عبور می‌کند. دسترسی به Activity از طریق controller.get() انجام می‌شود. همه کامپوننت‌های دید از طریق findViewById مانند برنامه واقعی در دسترس هستند. اشیاء shadow امکان بررسی متن‌ها، قابلیت مشاهده، رنگ‌ها و سایر ویژگی‌های view را فراهم می‌کنند.

java
@RunWith(RobolectricTestRunner.class)
@Config(sdk = BuildConfig.SDK_INT)
public class MainActivityTest {

    @Test
    public void testActivityDisplaysGreeting() {
        ActivityController<MainActivity> controller =
            Robolectric.buildActivity(MainActivity.class);
        controller.create().start().resume();

        MainActivity activity = controller.get();
        TextView greeting = activity.findViewById(R.id.greeting);
        ShadowTextView shadow = Shadows.shadowOf(greeting);

        assertEquals("Welcome!", shadow.getText());
    }
}

تست intentها و ناوبری

Robolectric فراخوانی‌های startActivity() را رهگیری می‌کند و امکان بررسی intentهای ارسال‌شده را از طریق ShadowActivity فراهم می‌کند. این امکان تست ناوبری را می‌دهد: بررسی اینکه با کلیک دکمه، Intent با Action، Data و پارامترهای Extra صحیح ارسال می‌شود.

java
@Test
public void testNavigationToDetails() {
    controller.create().start().resume();
    MainActivity activity = controller.get();

    activity.findViewById(R.id.detailsButton).performClick();

    ShadowActivity shadowActivity = Shadows.shadowOf(activity);
    Intent intent = shadowActivity.getNextStartedActivity();
    assertEquals(
        DetailsActivity.class.getName(),
        intent.getComponent().getClassName()
    );
}

Robolectric در مقابل شبیه‌ساز

Robolectric و شبیه‌ساز وظایف متفاوتی را حل می‌کنند. Robolectric برای تست‌های واحد سریع، بررسی منطق UI، کامپوننت‌های تجاری و مخازن ایده‌آل است. شبیه‌ساز برای تست‌های ابزاری، بررسی ادغام با API، تست دوربین، سنسورها و عملکرد ضروری است.

ویژگیRobolectricشبیه‌ساز
سرعت~5 ثانیه برای 100 تست~5 دقیقه برای 100 تست
راه‌اندازیبدون ساخت APKنیاز به ساخت APK
API واقعیشبیه‌سازی shadowAndroid SDK بومی
آماده استفادهفقط JUnitهر فریم‌ورکی

تست ViewModel و Repository

Robolectric برای تست ViewModel، Repository و UseCase — کامپوننت‌هایی که از Android SDK استفاده می‌کنند اما نیاز به UI واقعی ندارند — عالی است. ViewModel از طریق تست JUnit معمولی با RobolectricExtension تست می‌شود، در حالی که کامپوننت‌های چرخه حیات (LiveData، StateFlow) در محیط shadow بدون mock کار می‌کنند.

تست LiveData

Robolectric از LiveData به صورت آماده پشتیبانی می‌کند: می‌توان در تست روی LiveData مشترک شد، وضعیت را از طریق ViewModel تغییر داد و مقدار تولیدشده را بررسی کرد. برای عملیات ناهمگام از InstantTaskExecutorRule یا runBlocking برای کوروتین‌ها استفاده می‌شود. این نیاز به mock کردن کامپوننت‌های معماری را از بین می‌برد.

kotlin
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [BuildConfig.SDK_INT])
class ProfileViewModelTest {

    private val repository = FakeUserRepository()
    private val viewModel = ProfileViewModel(repository)

    @Test
    fun `loading profile sets state to success`() = runBlocking {
        viewModel.loadProfile("user123")
        val state = viewModel.profileState.getOrAwaitValue()
        Assertions.assertTrue(state is UiState.Success)
    }
}

اشیاء shadow سفارشی

اگر اشیاء shadow استاندارد Robolectric کلاس مورد نیاز Android SDK را پوشش نمی‌دهند، می‌توان Shadow سفارشی ایجاد کرد. برای این کار کلاسی با @Implements(ClassName.class) ایجاد شده و متدهای مورد نیاز با @Implementation پیاده‌سازی می‌شوند. shadowهای سفارشی از طریق @Config(shadows = [CustomShadow::class]) ثبت می‌شوند.

تست ContentProvider و Resources

Robolectric از تست ContentProvider از طریق Robolectric.buildContentProvider() پشتیبانی می‌کند. می‌توان عملیات CRUD، query با تطبیق URI و مدیریت مجوزهای دسترسی را بررسی کرد. منابع (رشته‌ها، رنگ‌ها، اندازه‌ها) نیز از طریق RuntimeEnvironment.application.resources در دسترس هستند که امکان تست کد وابسته به منابع را فراهم می‌کند.

مهاجرت از شبیه‌ساز به Robolectric

انتقال از تست‌های ابزاری به Robolectric نیاز به تغییر رویکرد دارد. تست‌های ابزاری (AndroidJUnit4) رفتار واقعی را روی شبیه‌ساز بررسی می‌کنند، Robolectric — منطق ایزوله‌شده در محیط shadow. توصیه می‌شود منطق تجاری را با تست‌های Robolectric پوشش داده و تست‌های ابزاری را برای سناریوهای ادغامی نگه دارید.

سازگاری تست‌های موجود

در مهاجرت لازم است: AndroidJUnit4 را با RobolectricTestRunner جایگزین کنید، @Config با نسخه SDK هدف اضافه کنید، ActivityTestRule را با ActivityController جایگزین کنید، و وابستگی‌ها را از androidTestImplementation به testImplementation منتقل کنید. Mockها (MockK، Mockito) با Robolectric بدون تغییر کار می‌کنند — آنها به پلتفرم وابسته نیستند.

محدودیت‌ها در مهاجرت

Robolectric پشتیبانی نمی‌کند: تست دوربین (CameraX)، NFC، بلوتوث، بیومتریک، کار با فایل‌های واقعی و کتابخانه‌های بومی. برای این سناریوها تست‌های ابزاری روی شبیه‌ساز ضروری هستند. Robolectric همچنین رندرینگ واقعی را بازتولید نمی‌کند — تست‌های layout بهتر است از طریق Compose Test Rule یا Espresso انجام شوند. با این حال برای بررسی منطق تجاری، ناوبری و وضعیت‌های ViewModel، Robolectric کاملاً جایگزین شبیه‌ساز با 10 برابر سرعت اجرا می‌شود.

سازگاری با نسخه‌های Java و Kotlin

Robolectric نیاز به JDK 11 یا بالاتر دارد و با AGP (Android Gradle Plugin) از 7.0 تا آخرین نسخه پایدار سازگار است. مدیر SDK Robolectric به طور خودکار نسخه‌های مورد نیاز Android API را در اولین اجرا دانلود می‌کند — این یک عملیات یک‌باره است. برای سرورهای CI توصیه می‌شود SDK را از قبل از طریق sdkmanager دانلود کنید تا از تأخیر در اولین اجرای تست جلوگیری شود. به‌روزرسانی Robolectric به نسخه جدید معمولاً نیازی به تغییر در کد تست‌ها ندارد، فقط به‌روزرسانی شماره وابستگی در build.gradle.

ادغام با MockK و Mockito

Robolectric با فریم‌ورک‌های mock محبوب سازگار است: MockK برای Kotlin و Mockito برای Java. Mockها برای ایزوله‌سازی وابستگی‌ها استفاده می‌شوند: مخازن، کلاینت‌های API، SharedPreferences. قانون اصلی — کلاس‌های Android SDK را mock نکنید، برای این کار اشیاء shadow وجود دارند. فقط لایه‌های برنامه را mock کنید: UseCase، Repository، DataSource و سایر کامپوننت‌های منطق تجاری. چنین ترکیبی از اشیاء shadow و mockها حداکثر انعطاف‌پذیری را با حداقل هزینه نوشتن تست فراهم می‌کند.

سوالات متداول

تفاوت Robolectric با Espresso چیست؟

Espresso یک فریم‌ورک ابزاری است که روی شبیه‌ساز یا دستگاه اجرا می‌شود. Robolectric یک فریم‌ورک واحد است که روی JVM کار می‌کند. Espresso رفتار واقعی را تست می‌کند، Robolectric — منطق ایزوله‌شده در محیط shadow. آنها مکمل یکدیگر هستند.

آیا می‌توان Jetpack Compose را با Robolectric تست کرد؟

بله، Robolectric از Jetpack Compose از نسخه 4.8 پشتیبانی می‌کند. تست‌های کامپوننت‌های Compose با ComposeTestRule مانند شبیه‌ساز انجام می‌شوند. با این حال تست‌های Compose روی Robolectric رندرینگ واقعی را بررسی نمی‌کنند — فقط منطق ترکیب.

Robolectric چگونه با ماژول‌های Gradle کار می‌کند؟

Robolectric از پروژه‌های چندماژولی پشتیبانی می‌کند. هر ماژول جداگانه با مشخص کردن manifest و منابع خود پیکربندی می‌شود. برای ماژول‌های بدون کامپوننت‌های UI، ماژول کتابخانه‌ای بدون پلاگین android کافی است. در پروژه‌های بزرگ با ده‌ها ماژول، تست‌های Robolectric هر ماژول به صورت موازی اجرا می‌شوند که سرعت بیشتری نسبت به اجرای ترتیبی روی شبیه‌ساز می‌دهد.

چرا Robolectric ممکن است منابع را پیدا نکند؟

مشکل منابع زمانی رخ می‌دهد که در build.gradle unitTests.includeAndroidResources = true مشخص نشده باشد یا @Config با مسیر صحیح به manifest وجود نداشته باشد. Robolectric از منابع کامپایل‌شده از build/intermediates استفاده می‌کند.

چگونه تست‌های Robolectric را debug کنیم؟

تست‌های Robolectric مانند تست‌های معمولی Java/Kotlin در Android Studio debug می‌شوند. breakpoint، step-through debug، بازرسی اشیاء shadow و وضعیت آنها در دسترس است. logging از طریق -Drobolectric.logging=debug در VM options فعال می‌شود.

خلاصه

  • Robolectric — فریم‌ورک تست واحد سریع Android روی JVM بدون شبیه‌ساز
  • اشیاء shadow بیش از 200 کلاس Android SDK را جایگزین می‌کنند و رفتار آنها را شبیه‌سازی می‌کنند
  • چرخه حیات Activity و Fragment از طریق ActivityController با بررسی وضعیت‌ها مدیریت می‌شود
  • تست intent از طریق ShadowActivity امکان بررسی ناوبری و انتقال داده را فراهم می‌کند
  • ادغام با JUnit و Gradle نیازی به runnerهای ابزاری اضافی ندارد
  • @Config نسخه API، زبان، پیکربندی صفحه و منابع را مشخص می‌کند
  • Robolectric و Espresso مکمل یکدیگر هستند: تست‌های واحد سریع در مقابل تست‌های ابزاری

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید