Pengujian Unit dalam Pengembangan Mobile: Apa Itu, Metode, dan Framework

Penulis: IT Sectr Diterbitkan: 2026-04-06 Waktu membaca: 9 mnt

Pengujian unit adalah metode verifikasi perangkat lunak di mana kebenaran kerja modul atau fungsi kode individu diuji secara terisolasi dari seluruh sistem. Menurut Martin Fowler, 2026, pengujian unit adalah fondasi CI/CD dan refactoring, memberikan umpan balik cepat tentang kelayakan kode. Pengujian modular membantu menemukan kesalahan pada tahap awal pengembangan, mengurangi biaya perbaikannya hingga puluhan kali lipat.

Poin Utama

  • Pengujian unit — pemeriksaan satu modul (fungsi, metode, kelas) secara terisolasi dari ketergantungan eksternal
  • Prinsip FIRST — Fast, Isolated, Repeatable, Self-validating, Timely — dasar pengujian berkualitas
  • Mock dan stub — pengganti ketergantungan eksternal (database, API, sistem file), memastikan isolasi pengujian
  • TDD (Test-Driven Development) — metodologi pengembangan melalui pengujian: merah-hijau-refactoring
  • Piramida pengujian — pengujian unit menempati 70% piramida, memberikan umpan balik cepat pada setiap commit

Apa itu pengujian unit?

Pengujian unit adalah proses pemeriksaan unit individu kode sumber — fungsi, metode, kelas — secara terisolasi dari seluruh program. Setiap pengujian menjalankan skenario penggunaan modul tertentu dan memeriksa apakah hasilnya sesuai dengan yang diharapkan. Pengujian unit ditulis dalam bahasa pemrograman yang sama dengan kode utama dan dijalankan secara otomatis di lingkungan pengembangan atau di pipeline CI/CD. Berbeda dengan pengujian integrasi, pengujian unit tidak berinteraksi dengan database nyata, sistem file, atau layanan jaringan.

Mengapa pengujian unit diperlukan?

Tujuan utamanya adalah umpan balik cepat tentang kebenaran kode setelah perubahan. Jika pengembang melakukan refactoring pada suatu metode, kumpulan pengujian unit memastikan bahwa perilaku tidak rusak. Menurut Google Testing Blog (2025), proyek dengan cakupan pengujian unit di atas 60% memiliki 2,5 kali lebih sedikit insiden produksi. Keuntungan tambahan: dokumentasi kode (pengujian menunjukkan cara menggunakan API), penyederhanaan refactoring (implementasi dapat diubah sambil mempertahankan perilaku), dan diagnosis regresi yang cepat.

Apa yang dianggap sebagai pengujian unit?

Tidak semua pengujian otomatis adalah pengujian unit. Kriteria: satu modul (kelas atau fungsi) diuji, ketergantungan eksternal diganti dengan mock atau stub, pengujian dijalankan dalam milidetik, tidak memerlukan menjalankan server atau database. Pengujian yang mengakses database nyata adalah pengujian integrasi. Pengujian yang membuka browser adalah pengujian E2E. Memahami batas antara jenis pengujian penting untuk distribusi upaya yang tepat dalam piramida pengujian.

Prinsip FIRST dan struktur AAA

Pengujian unit berkualitas mengikuti prinsip FIRST yang dirumuskan oleh Robert C. Martin. Setiap pengujian harus Fast (cepat — milidetik), Isolated (terisolasi — tidak bergantung pada pengujian lain), Repeatable (dapat diulang — hasil sama di mesin mana pun), Self-validating (memvalidasi sendiri — hasilnya “passed” atau “failed”, tanpa pemeriksaan manual), dan Timely (tepat waktu — ditulis sebelum atau bersamaan dengan kode). Pelanggaran prinsip mana pun mengurangi nilai pengujian.

Struktur AAA (Arrange-Act-Assert)

Pola standar untuk menulis pengujian unit. Arrange — persiapan data dan ketergantungan: pembuatan objek, konfigurasi mock, pengaturan parameter input. Act — pelaksanaan tindakan yang diuji: pemanggilan metode atau fungsi. Assert — pemeriksaan hasil: perbandingan nilai aktual dengan yang diharapkan. Pembagian menjadi tiga blok membuat pengujian mudah dibaca dan dipahami. Jika blok Assert memerlukan logika kompleks, kemungkinan pengujian memeriksa terlalu banyak hal sekaligus.

kotlin
// Contoh pengujian unit dengan pola AAA di Kotlin dengan JUnit 5
class CalculatorTest {

    private lateinit var calculator: Calculator

    @BeforeEach
    fun setUp() {
        // ARRANGE — kita buat objek yang diuji
        calculator = Calculator()
    }

    @Test
    fun addition_shouldReturnCorrectSum() {
        // ACT — kita lakukan tindakan
        val result = calculator.add(2, 3)

        // ASSERT — kita periksa hasilnya
        Assertions.assertEquals(5, result)
    }
}

Penamaan pengujian

Nama pengujian harus menjelaskan apa yang diperiksa dan hasil apa yang diharapkan. Format: [methodName]_[scenario]_[expectedResult]. Contoh: calculateTotal_whenDiscountApplied_shouldReturnDiscountedTotal. Nama pengujian yang baik menggantikan komentar dan saat gagal langsung menunjukkan fungsionalitas mana yang rusak. Hindari nama seperti test1, checkSomething, atau verify — mereka tidak membawa informasi dan mempersulit diagnosis.

Mock, stub, dan fake: apa dan kapan menggunakannya

Untuk mengisolasi modul yang diuji dari ketergantungan eksternal, digunakan pengganti pengujian (test doubles). Jenis utama: mock — memeriksa apakah metode tertentu dipanggil dengan parameter yang benar; stub — mengembalikan nilai yang ditentukan saat metode dipanggil; fake — implementasi sederhana dari komponen nyata (misalnya, InMemoryUserRepository sebagai ganti UserRepository yang bekerja dengan database). Pilihan tergantung pada apa yang perlu diperiksa: kondisi (stub) atau interaksi (mock).

PenggantiApa yang diperiksaContoh
MockPanggilan metode dengan parameter benaruserRepository.save(user) dipanggil tepat 1 kali
StubNilai yang dikembalikanrepository.findById(1) mengembalikan User(id=1, name=“Test”)
FakeLogika melalui implementasi sederhanaInMemoryMapUserRepository dengan HashMap sebagai ganti database
SpyMocking parsial objek nyataspy(repo).when(findById).thenReturn(user)

Mockito: contoh mocking di Java/Kotlin

Mockito adalah framework mocking paling populer di Java dan Kotlin. Memungkinkan pembuatan mock melalui mock(), konfigurasi nilai kembali melalui when().thenReturn(), dan pemeriksaan panggilan melalui verify(). Versi modern Mockito (5.x) mendukung mock statis (mockStatic) dan sintaksis yang disederhanakan melalui BDDMockito (given-willReturn). Aturan penting: jangan mock sesuatu yang bukan milik Anda — jangan buat mock untuk objek nilai dan pustaka standar.

kotlin
// Contoh pengujian unit dengan Mockito di Kotlin
class OrderServiceTest {

    @Mock
    private lateinit var paymentGateway: PaymentGateway

    @Mock
    private lateinit var userRepository: UserRepository

    private lateinit var orderService: OrderService

    @BeforeEach
    fun init() {
        MockitoAnnotations.openMocks(this)
        orderService = OrderService(paymentGateway, userRepository)
    }

    @Test
    fun processOrder_whenPaymentFails_shouldThrowException() {
        // given
        val user = User(id = 1, balance = 100.0)
        val order = Order(amount = 200.0)
        Mockito.`when`(paymentGateway.charge(any())).thenReturn(false)
        Mockito.`when`(userRepository.findById(1)).thenReturn(user)

        // when & then
        assert Throws<PaymentException> {
            orderService.processOrder(user.id, order)
        }

        // verify
        Mockito.verify(paymentGateway).charge(any())
    }
}

TDD: pengembangan melalui pengujian

TDD (Test-Driven Development) — metodologi di mana pengujian ditulis sebelum implementasi kode. Siklus “Red-Green-Refactor”: tulis pengujian yang gagal (Red), tulis kode minimal untuk lulus pengujian (Green), tingkatkan kode tanpa mengubah perilaku (Refactor). TDD memastikan bahwa semua kode tercakup oleh pengujian (cakupan = 100% untuk fungsionalitas yang ditulis) dan bahwa kode dapat diuji — jika kode sulit diuji, berarti arsitektur perlu perbaikan.

Keuntungan TDD

Menurut penelitian IBM (2006-2026, studi longitudinal), tim yang menggunakan TDD membuat 40-80% lebih sedikit cacat dalam produksi dibandingkan dengan tim yang menulis pengujian setelah kode. TDD juga meningkatkan arsitektur: pengembang harus memikirkan desain API sebelum implementasi, yang menghasilkan kopling longgar (loose coupling) dan kohesi tinggi (high cohesion). Efek tambahan — dokumentasi dengan kode hidup: pengujian berfungsi sebagai spesifikasi perilaku modul yang selalu terkini.

Kapan TDD tidak cocok?

TDD tidak selalu optimal. Komponen UI sulit diuji secara terisolasi — untuk mereka, pengujian snapshot atau pengujian regresi visual (Percy, Chromatic) lebih efektif. Prototipe dan penelitian (spike solutions) tidak memerlukan pengujian. Kode legacy tanpa pengujian sulit dicakup melalui TDD — di sini pertama-tama diperlukan characterization tests (pengujian yang merekam perilaku saat ini sebelum refactoring). Dalam kasus ini, TDD tidak sepenuhnya dihapuskan, tetapi disesuaikan — pengujian ditulis untuk fungsionalitas yang diubah, bukan untuk seluruh kode legacy.

Pengujian unit dalam aplikasi mobile

Pengembangan mobile memiliki spesifikasinya: logika bisnis sering tercampur dengan kode UI (Activity, ViewController, ViewModel), yang mempersulit pengujian unit. Praktik terbaik — tampilan tipis, ViewModel tebal: pindahkan semua logika dari komponen UI ke kelas terpisah (UseCase, Repository, ViewModel) yang mudah diuji tanpa emulator. Untuk Android dan iOS, ada framework pengujian unit native yang berjalan di JVM/Native tanpa menjalankan perangkat.

Pengujian unit di Android (JUnit + Mockito/Robolectric)

Pengujian unit Android dijalankan di JVM lokal tanpa emulator, yang memastikan kecepatan eksekusi — pengujian tipikal membutuhkan waktu kurang dari 100ms. JUnit 5 adalah runner utama. Untuk pengujian ViewModel, gunakan kotlinx-coroutines-test untuk menguji coroutine dan Turbine untuk menguji StateFlow. Robolectric memungkinkan pengujian komponen dependen Android (Context, Resources) tanpa emulator dengan memuat shadow class. Untuk pengujian Compose, gunakan Compose UI Test — tetapi ini sudah merupakan pengujian UI, bukan unit.

Pengujian unit di iOS (XCTest + Quick/Nimble)

Pengujian unit iOS ditulis dalam Swift dengan XCTest (terintegrasi di Xcode). Quick + Nimble — framework BDD untuk pengujian yang lebih mudah dibaca (describe/context/it). Untuk mocking, gunakan Cuckoo (generasi mock) atau SwiftyMocky. Swift mendukung protokol dan dependency injection, yang memudahkan penggantian ketergantungan. Poin penting: pengujian unit iOS dijalankan di simulator macOS, bukan di perangkat nyata. Pengujian yang memerlukan fungsi perangkat keras (kamera, Bluetooth) adalah pengujian integrasi.

Pengujian unit di Flutter (flutter_test + Mockito)

Pengujian unit Flutter menggunakan paket flutter_test dan dijalankan di Dart VM tanpa emulator. Untuk mocking — paket mockito dengan generator kode (build_runner). Pengujian widget (dalam paket yang sama) menguji widget individu, tetapi memerlukan rendering dan berjalan lebih lambat — gunakan hanya untuk memeriksa logika UI. Logika Dart murni (model, repositori, blobs) diuji seperti pengujian Dart biasa tanpa mengimpor flutter_test.

dart
// Contoh pengujian unit di Flutter dengan mockito
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';

@GenerateMocks([ApiClient])
import 'user_repository_test.mocks.dart';

void main() {
    late MockApiClient mockApi;
    late UserRepository repository;

    setUp(() {
        mockApi = MockApiClient();
        repository = UserRepository(mockApi);
    });

    test('fetchUser returns user when API succeeds', () async {
        // Arrange
        final expectedUser = User(id: 1, name: 'Test');
        when(mockApi.getUser(1))
            .thenAnswer((_) async => expectedUser);

        // Act
        final result = await repository.fetchUser(1);

        // Assert
        expect(result, expectedUser);
        verify(mockApi.getUser(1)).called(1);
    });
}

Praktik terbaik dan kesalahan umum

Pengujian unit yang efektif memerlukan disiplin. Aturan utama: uji perilaku, bukan implementasi. Pengujian tidak boleh tahu bagaimana modul diimplementasikan secara internal (metode privat apa yang dipanggil, dalam urutan apa). Jika pengujian terikat pada implementasi, ia rusak pada setiap refactoring dan kehilangan nilai. Pengujian memeriksa kontrak: dengan input X harus ada output Y. Pengecualian — pengujian untuk algoritma dengan kinerja kritis, di mana urutan panggilan penting.

  • Satu pemeriksaan per pengujian — satu assert atau satu grup assert terkait untuk satu pemeriksaan logis
  • Hindari duplikasi — gunakan @BeforeEach / setUp untuk inisialisasi bersama, pengujian berparameter untuk data input berbeda
  • Jangan uji metode privat — uji melalui API publik. Jika metode privat tidak tercakup, logikanya tidak terlihat dari luar
  • Cakup kasus batas — koleksi kosong, null/undefined, angka negatif, nilai maksimum
  • Jangan gunakan Thread.sleep dalam pengujian — ini membuat pengujian lambat dan tidak stabil. Gunakan timeout pengujian dan coroutine

Tingkat cakupan apa yang cukup?

Cakupan 100% adalah tujuan yang tidak dapat dicapai dan tidak diperlukan. Menurut Google Testing Blog (2025), tingkat cakupan optimal untuk pengujian unit adalah 70-80% baris kode. Cakupan 100% sering dicapai dengan menguji getter, setter, dan konstruktor, yang tidak memberikan nilai. Fokus pada logika bisnis kritis: perhitungan kompleks, validasi, penanganan kesalahan, kasus tepi. Gunakan JaCoCo (Java), Coverage.py (Python), Istanbul (JS) untuk pengukuran dan atur ambang batas di CI — kegagalan build pada cakupan di bawah 60%.

CI/CD dan pengujian unit

Pengujian unit adalah tahap pertama dari setiap pipeline CI/CD. Mereka dijalankan pada setiap push ke repositori, sebelum build dan deploy. Waktu eksekusi rata-rata pengujian unit dalam proyek tidak boleh melebihi 5 menit — jika lebih lama, pengujian tidak lagi “epat” dan pengembang berhenti menjalankannya secara lokal. Bagilah pengujian menjadi cepat (unit) dan lambat (integrasi) dan jalankan di berbagai tahap pipeline. Gunakan eksekusi paralel dan fail-fast untuk mempercepat.

Pertanyaan yang Sering Diajukan

Apa perbedaan pengujian unit dengan pengujian integrasi?

Pengujian unit memeriksa satu modul secara terisolasi, mengganti ketergantungan eksternal dengan mock. Pengujian integrasi memeriksa interaksi antara beberapa komponen nyata (database, API, sistem file). Pengujian unit dijalankan dalam milidetik, pengujian integrasi dalam detik. Dalam piramida pengujian, pengujian unit menempati 70%.

Framework mana yang harus dipilih untuk pengujian unit?

Pilihan tergantung pada platform: JUnit 5 untuk Java/Kotlin, XCTest untuk iOS/Swift, pytest untuk Python, Jest/Vitest untuk JavaScript/TypeScript, flutter_test untuk Flutter. Untuk mocking, gunakan Mockito (Java), Cuckoo (iOS), unittest.mock (Python), atau vitest.mock (JS). Semua framework modern mendukung pengujian berparameter, assert bawaan, dan eksekusi paralel.

Apa itu prinsip F.I.R.S.T. dalam pengujian?

Fast — pengujian dijalankan dalam milidetik. Isolated — tidak bergantung pada pengujian lain dan sistem eksternal. Repeatable — memberikan hasil yang sama di mesin mana pun. Self-validating — memeriksa hasil secara otomatis. Timely — ditulis sebelum atau sinkron dengan kode. Pelanggaran salah satu prinsip mengurangi efektivitas pengujian.

Apakah perlu menulis pengujian unit untuk ViewModel di Android/iOS?

Ya, wajib. ViewModel berisi logika bisnis — penanganan peristiwa, transformasi data, manajemen status. Di Android, gunakan kotlinx-coroutines-test untuk coroutine dan Turbine untuk menguji StateFlow. Di iOS, uji Combine Publishers atau async/await di ViewModel. Pengujian ViewModel adalah pengujian unit murni yang berjalan di JVM/macOS tanpa emulator.

Bagaimana cara menguji kode dengan permintaan jaringan?

Permintaan jaringan dalam pengujian unit tidak dijalankan — mereka diganti dengan mock klien HTTP. Di Android, gunakan MockWebServer (OkHttp) — ini menjalankan server HTTP lokal, yang lebih disukai daripada mock karena mereproduksi interaksi jaringan nyata. MockWebServer memberikan isolasi tanpa kehilangan realisme. Untuk iOS — OHHTTPStubs atau URLProtocol untuk mencegat dan mengganti respons.

Kesimpulan

  • Pengujian unit — pemeriksaan modul individu secara terisolasi dari ketergantungan eksternal dengan umpan balik cepat
  • Struktur AAA — Arrange (persiapan), Act (tindakan), Assert (pemeriksaan) — pola standar pengujian
  • Mock dan stub — pengganti pengujian untuk isolasi: mock memeriksa panggilan, stub mengembalikan nilai
  • TDD — pengembangan melalui pengujian (Red-Green-Refactor) mengurangi cacat sebesar 40-80%
  • Prinsip FIRST — Fast, Isolated, Repeatable, Self-validating, Timely — dasar pengujian berkualitas
  • Alat platform — JUnit 5 (Android), XCTest (iOS), flutter_test (Flutter), Jest (React Native)
  • Cakupan 70-80% — tingkat optimal untuk logika bisnis kritis, getter dan setter tidak memerlukan pengujian

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga