Mockito adalah framework sumber terbuka untuk membuat objek mock dalam pengujian unit Java dan Kotlin, yang memungkinkan isolasi kode yang diuji dari dependensi eksternal. Dengan bantuannya, pengembang mengganti repositori nyata, klien API, dan basis data dengan tiruan yang terkendali dengan perilaku yang ditentukan. Menurut data Mockito.org, perpustakaan ini digunakan di lebih dari 60% proyek Java yang menerapkan pengujian unit.
Poin Utama
Mockito adalah perpustakaan sumber terbuka untuk membuat objek mock (tiruan) dalam pengujian unit di Java, Kotlin, dan bahasa JVM lainnya. Berbeda dengan JUnit yang bertanggung jawab menjalankan pengujian, Mockito memecahkan masalah isolasi — menggantikan dependensi nyata dari kelas yang diuji dengan objek yang dapat diprediksi.
Tanpa mock, menguji metode yang mengakses basis data atau API eksternal memerlukan pengaturan lingkungan nyata — menjalankan DB, memulai server. Mockito menggantikan dependensi ini dengan objek berperilaku tetap: metode repository.findById(1) selalu mengembalikan objek User tertentu, tanpa mengakses basis data.
Arsitektur Mockito didasarkan pada pola Proxy (untuk antarmuka dan kelas). Perpustakaan menghasilkan subkelas atau proksi untuk tipe yang ditentukan dan mencegat semua panggilan metode, mengembalikan nilai default atau nilai yang ditentukan melalui when().thenReturn().
Prinsip kerja Mockito didasarkan pada tiga operasi dasar: membuat mock, mengonfigurasi perilaku (stubbing), dan memverifikasi panggilan (verification). Setiap operasi menggunakan metode statis dari kelas org.mockito.Mockito — kelas yang paling banyak dimuat di ekosistem Java menurut statistik Maven Central. Semua panggilan metode mock dicatat dalam memori, yang memungkinkan pemeriksaan selanjutnya melalui verify.
Pengujian tipikal dengan Mockito terdiri dari tiga fase: Arrange — membuat mock dan mengonfigurasi stub melalui when().thenReturn(), Act — memanggil metode yang diuji, Assert — memeriksa hasil melalui assertEquals dan verify(mock). Pendekatan ini disebut AAA (Arrange-Act-Assert).
Mari kita lihat pengujian sederhana di mana Mockito menggantikan repositori pengguna. Metode when().thenReturn() mengonfigurasi mock sehingga panggilan findById mengembalikan objek User yang telah disiapkan sebelumnya.
// Kita buat mock repositori
UserRepository mockRepo = mock(UserRepository.class);
// Konfigurasi perilaku: saat findById(1) kembalikan pengguna
when(mockRepo.findById(1)).thenReturn(new User("Alice"));
// Periksa apakah metode benar-benar dipanggil
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);
Mockito menyediakan dua cara membuat mock: metode statis mock(Class) dan anotasi @Mock dengan inisialisasi melalui MockitoAnnotations.openMocks(). Cara pertama ringkas untuk satu-dua mock, cara kedua nyaman ketika dependensi banyak — anotasi mengurangi kode boilerplate.
Metode mock() menerima kelas dan mengembalikan objek tiruan yang dapat dikonfigurasi melalui when().thenReturn(). Semua metode yang tidak dikonfigurasi mengembalikan nilai default: 0 untuk angka, false untuk boolean, null untuk objek.
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);
Anotasi @Mock bersama dengan @ExtendWith(MockitoExtension.class) secara otomatis membuat mock untuk semua bidang kelas pengujian. Ekstensi MockitoExtension bertanggung jawab untuk inisialisasi sebelum setiap pengujian.
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void getUserShouldReturnUserFromRepo() {
when(userRepository.findById(1)).thenReturn(new User("Alice"));
User result = userService.getUser(1);
assertEquals("Alice", result.getName());
}
}
Stubbing — proses menentukan apa yang harus dikembalikan oleh metode mock ketika dipanggil dengan argumen tertentu. Sintaks dasar: when(mock.method(args)).thenReturn(value). Untuk skenario berbeda, Mockito menawarkan beberapa varian metode then.
| Metode | Tujuan |
|---|---|
| thenReturn(value) | Selalu mengembalikan nilai yang ditentukan |
| thenThrow(exception) | Melempar pengecualian saat dipanggil |
| thenAnswer(answer) | Menghitung nilai kembalian secara dinamis |
| thenCallRealMethod() | Memanggil metode nyata (mock parsial) |
Ketika nilai kembalian tergantung pada argumen panggilan, digunakan thenAnswer dengan lambda. Ini berguna untuk simulasi bekerja dengan data nyata — misalnya, menghasilkan ID berdasarkan objek yang diteruskan.
when(repository.save(any())).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(42);
return user;
});
Verify adalah kemampuan unik Mockito yang tidak disediakan oleh perpustakaan objek mock yang lebih lama (EasyMock, jMock).
Verify membuat pengujian lebih andal, karena tidak hanya memeriksa nilai kembalian, tetapi juga efek samping — panggilan metode yang tidak mengembalikan hasil (metode void). Metode verify(mock).methodName(args) memeriksa apakah metode mock tertentu telah dipanggil dengan argumen yang ditentukan. Ini memungkinkan pengujian tidak hanya hasil, tetapi juga proses — fakta akses ke dependensi.
Secara default, verify memeriksa bahwa metode telah dipanggil tepat satu kali. Jika jumlah yang berbeda diperlukan — gunakan times(n), atLeast(n), never() dan pengubah lainnya dari kelas Mockito.
// Memeriksa jumlah panggilan
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);
// Memeriksa urutan panggilan
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();
Ketika perlu memeriksa dengan objek apa tepatnya metode dipanggil, digunakan ArgumentCaptor. Ini menangkap nilai argumen selama panggilan dan memungkinkan pemeriksaan bidangnya secara terpisah. ArgumentCaptor sangat berguna ketika kode yang diuji membuat objek di dalamnya dan meneruskannya ke dependensi — Anda tidak dapat memeriksa objek ini dengan cara lain.
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());
@Mock dan @InjectMocks — dua anotasi kunci Mockito yang secara signifikan mengurangi kode boilerplate. @Mock membuat mock untuk bidang, dan @InjectMocks menyuntikkan semua mock dari kelas pengujian ke objek yang diuji melalui konstruktor, setter, atau bidang.
Mekanisme @InjectMocks mencoba menyuntikkan dependensi dalam urutan berikut: konstruktor dengan jumlah argumen terbanyak, setter berdasarkan tipe, bidang privat. Jika tidak ada cara yang berhasil — objek tetap dengan dependensi null dan pengujian gagal dengan NullPointerException.
Penting untuk dipahami: @InjectMocks tidak menganalisis tipe bidang — ia menggantikan mock apa pun yang kompatibel dengan tipe. Jika kelas memiliki dua bidang dengan tipe yang sama — Mockito dapat menyuntikkan mock yang salah. Dalam kasus seperti itu, disarankan menggunakan konstruktor eksplisit dengan meneruskan mock.
Dalam pengembangan Android, Mockito digunakan bersama JUnit untuk menguji ViewModel, Repository, dan UseCase. Karena kelas-kelas ini berjalan di JVM tanpa konteks Android, Mockito menggantikan dependensi mereka — Room DAO, Retrofit API, SharedPreferences — dengan stub berperilaku dapat diprediksi.
Untuk menambahkan Mockito ke proyek Android, cukup tambahkan dependensi mockito-core atau mockito-inline (yang terakhir mendukung mocking kelas final dan metode statis). Versi 5.12.0 (2024) mencakup dukungan Java 21 dan integrasi yang ditingkatkan dengan JUnit 5.
// build.gradle.kts (modul)
dependencies {
testImplementation("org.mockito:mockito-core:5.12.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}
Sebelumnya, untuk mocking metode statis dan konstruktor diperlukan PowerMock — ekstensi yang bekerja melalui instrumentasi bytecode. Mulai Mockito 5.x dengan mockito-inline, fungsionalitas ini terintegrasi langsung: mockStatic(ClassName.class) memungkinkan mocking metode statis tanpa perpustakaan tambahan.
Skenario tipikal: ViewModel memanggil metode repositori dan mengubah hasilnya menjadi status UI. Mockito menggantikan repositori, dan pengujian memeriksa apakah ViewModel memproses respons sukses dan kesalahan dengan benar. Saat menggunakan arsitektur Clean Architecture, mock dibuat untuk setiap lapisan: DataSource, Repository, dan UseCase — ini memungkinkan pengujian setiap lapisan secara terisolasi.
Pertanyaan Umum
Mockito adalah perpustakaan untuk Java dan Kotlin yang menggunakan proxy dan refleksi. MockK adalah perpustakaan Kotlin-first dengan dukungan untuk coroutine, fungsi ekstensi, dan kelas final tanpa konfigurasi tambahan.
Sejak Mockito 2.1, mocking kelas final didukung melalui opt-in. Di versi 5.x (mockito-inline) ini diaktifkan secara default. Cukup tambahkan dependensi mockito-inline dan gunakan metode mock() standar.
Spy adalah mock parsial yang secara default memanggil metode nyata, tetapi memungkinkan mengganti beberapa di antaranya melalui when().thenReturn(). Spy berguna untuk menguji kode legacy ketika seluruh kelas tidak dapat ditulis ulang.
thenReturn selalu mengembalikan nilai yang sama, terlepas dari argumen. thenAnswer menghitung nilai kembalian berdasarkan pemanggilan — argumen, mock itu sendiri, status. Untuk jawaban dinamis, selalu gunakan thenAnswer.
Verify memeriksa tidak hanya hasil, tetapi juga proses — fakta akses ke dependensi. Ini penting untuk layanan yang harus menyimpan data atau mengirim pemberitahuan. Tanpa verify, pengujian tidak akan mendeteksi bahwa metode tidak memanggil save() atau send().
Ringkasan
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.
Baca juga