Melakukan Mocking Metode Statis dan Konstruktor
Pelajari teknik tingkat lanjut untuk melakukan mock pada metode statis, kelas final, dan konstruktor menggunakan ekstensi Mockito seperti `mockito-inline`.
Melakukan Mocking Metode Statis dan Konstruktor adalah pelajaran Testing Mastery: JUnit, Mockito & Integration Tests gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Testing Mastery: JUnit, Mockito & Integration Tests, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Testing Mastery: JUnit, Mockito & Integration Tests mencakup 4 pelajaran total.
Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.
Beyond Regular Mocks
Welcome! So far, you've learned to mock interfaces and regular classes using Mockito. But what about those tricky bits of code that seem resistant to testing?
Sometimes, you encounter static methods, final classes, or direct constructor calls (new MyObject()) within the code you want to test. Standard Mockito can't handle these directly.
When Traditional Mocks Fail
Why do we need to mock these?
- Static utility methods: Often used for common tasks, but hard to isolate if they have side effects or external dependencies.
- Final classes/methods: Cannot be subclassed or overridden, making traditional proxy-based mocking impossible.
- Constructor calls (
new): Direct object creation within a method makes it hard to inject a mock instead.
Mocking these helps you isolate the code under test, even in complex or legacy systems.
Powering Up Mockito
To overcome these limitations, Mockito offers advanced capabilities through its inline mock maker, often referred to as mockito-inline.
This feature uses byte-code manipulation to "rewrite" classes at runtime, allowing Mockito to mock things it normally can't, such as static methods, final classes, and even constructors.
It's a powerful tool, but use it thoughtfully!
Setting Up Your Project
For Mockito versions 3.4.0 and newer, the inline mock maker is often enabled by default or available simply by using the standard mockito-core dependency.
If you're using an older version or encountering issues, you might need to explicitly declare mockito-inline. For most modern setups, just ensure you have a recent mockito-core version.
Here's how your build.gradle might look:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
testImplementation 'org.mockito:mockito-core:5.8.0' // Includes inline mock maker
// For older Mockito versions, you might need:
// testImplementation 'org.mockito:mockito-inline:5.8.0'
}Mocking Static Helpers
To mock static methods, Mockito provides the MockedStatic interface. You create a mock context using Mockito.mockStatic() within a try-with-resources block. This ensures the mock is active only for the duration of that block.
Let's see an example with a utility class:
import org.mockito.Mockito;
import org.mockito.MockedStatic;
// Utility class with a static method
class MyStaticService {
public static String getGreeting() {
return "Hello from real static service!";
}
public static int add(int a, int b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Before mock: " + MyStaticService.getGreeting());
// Mock the static method within a try-with-resources
try (MockedStatic<MyStaticService> mockedStatic = Mockito.mockStatic(MyStaticService.class)) {
mockedStatic.when(MyStaticService::getGreeting).thenReturn("Hello from mocked static!");
mockedStatic.when(() -> MyStaticService.add(1, 2)).thenReturn(100);
System.out.println("During mock (greeting): " + MyStaticService.getGreeting());
System.out.println("During mock (add): " + MyStaticService.add(1, 2));
System.out.println("During mock (add other): " + MyStaticService.add(5, 5)); // Not mocked, returns 0 by default
// Verify calls (typically in a test assertion)
mockedStatic.verify(MyStaticService::getGreeting);
mockedStatic.verify(() -> MyStaticService.add(1, 2), Mockito.times(1));
} // Mock is closed here
System.out.println("After mock: " + MyStaticService.getGreeting());
}
}Checking Static Interactions
Just like with regular mocks, you can verify interactions with static methods. Use the verify() method on your MockedStatic object.
This ensures that your code under test called the static method as expected, with the correct arguments and number of times.
Notice the Mockito.times(1) in the previous example to check invocation count.
import org.mockito.Mockito;
import org.mockito.MockedStatic;
// Class from previous scene
class MyStaticService {
public static String getGreeting() { return "Hello from real static!"; }
public static int multiply(int a, int b) { return a * b; }
}
public class Main {
public static void main(String[] args) {
// Simulate a scenario where a static method is called
System.out.println("Initial call: " + MyStaticService.multiply(2, 3));
try (MockedStatic<MyStaticService> mockedStatic = Mockito.mockStatic(MyStaticService.class)) {
mockedStatic.when(() -> MyStaticService.multiply(2, 3)).thenReturn(777);
mockedStatic.when(() -> MyStaticService.multiply(5, 5)).thenReturn(123);
// Call the static method through the mock
System.out.println("Mocked call 1: " + MyStaticService.multiply(2, 3));
System.out.println("Mocked call 2: " + MyStaticService.multiply(5, 5));
// Verify specific calls
mockedStatic.verify(() -> MyStaticService.multiply(2, 3), Mockito.times(1));
mockedStatic.verify(() -> MyStaticService.multiply(5, 5), Mockito.atLeastOnce());
// Verify that a different call was NOT made
mockedStatic.verify(() -> MyStaticService.multiply(10, 10), Mockito.never());
System.out.println("Verifications completed.");
} // Mock is closed here
}
}Taming Final Classes
The mockito-inline mock maker also allows you to mock final classes and final methods. This is particularly useful when dealing with third-party libraries or legacy code where you can't easily change the class design.
You mock final classes just like regular classes: Mockito.mock(FinalClass.class).
import org.mockito.Mockito;
// A final class that cannot be extended normally
final class FinalProcessor {
public final String process(String input) {
return "Real processed: " + input.toUpperCase();
}
public int getVersion() {
return 1;
}
}
public class Main {
public static void main(String[] args) {
FinalProcessor realProcessor = new FinalProcessor();
System.out.println("Real output: " + realProcessor.process("data"));
System.out.println("Real version: " + realProcessor.getVersion());
// Mocking a final class
FinalProcessor mockProcessor = Mockito.mock(FinalProcessor.class);
// Stubbing a final method
Mockito.when(mockProcessor.process("data")).thenReturn("Mocked processed: data");
Mockito.when(mockProcessor.getVersion()).thenReturn(99);
System.out.println("Mocked output: " + mockProcessor.process("data"));
System.out.println("Mocked version: " + mockProcessor.getVersion());
// Verify interaction with the mocked final class
Mockito.verify(mockProcessor).process("data");
}
}Intercepting New Objects
What if your code creates new objects directly using new MyObject()? MockedConstruction lets you intercept these calls and return mock instances instead of real ones.
This is crucial for testing classes that internally manage their dependencies rather than receiving them via dependency injection.
import org.mockito.Mockito;
import org.mockito.MockedConstruction;
// A class that creates another object internally
class DependentService {
private final Helper helper;
public DependentService() {
this.helper = new Helper(); // Direct constructor call
}
public String doWork() {
return "Service working with: " + helper.getGreeting();
}
}
// The class whose constructor we want to mock
class Helper {
public String getGreeting() {
return "Real Helper greeting";
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Without mock:");
DependentService realService = new DependentService();
System.out.println(realService.doWork());
System.out.println("\nWith mocked construction:");
// Mock the constructor of Helper
try (MockedConstruction<Helper> mockedConstruction = Mockito.mockConstruction(Helper.class,
(mock, context) -> {
// This block runs every time new Helper() is called
Mockito.when(mock.getGreeting()).thenReturn("Mocked Helper greeting!");
System.out.println("Helper constructor intercepted!");
})) {
// When DependentService() is called, it calls new Helper(),
// which now returns our stubbed mock.
DependentService serviceWithMockedHelper = new DependentService();
System.out.println(serviceWithMockedHelper.doWork());
// You can get all constructed mocks
Helper constructedMock = mockedConstruction.constructed().get(0);
Mockito.verify(constructedMock).getGreeting(); // Verify interaction with the mock
System.out.println("Verified mock interaction.");
} // MockedConstruction is closed here
}
}Use With Care
While powerful, mocking statics and constructors can be an indicator of a design that's hard to test.
- Design Smell: Heavily relying on these mocks might suggest your classes are too tightly coupled or not following dependency injection principles.
- Readability: Tests using these advanced mocks can be harder to understand and maintain.
- When to use: Best for legacy code, third-party libraries, or when refactoring isn't immediately feasible. Prioritize refactoring for testability when possible!
Advanced Mocking Check
Which of the following statements about mockito-inline and advanced mocking techniques are TRUE?
Advanced Mocking Recap
Great job! You've explored advanced Mockito techniques:
- The
mockito-inlinemock maker enables mocking of statics, final classes, and constructors. MockedStaticallows you to stub and verify static method calls within a defined scope.MockedConstructionhelps intercept and replace objects created via thenewkeyword.
These tools are powerful for testing challenging code, but remember to consider underlying design patterns. Next, you'll learn about Mockito best practices!
Belajar Testing Mastery: JUnit, Mockito & Integration Tests dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 12
- Pelajaran
- 48
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Melakukan Mocking Metode Statis dan Konstruktor” gratis?
Ya — teks lengkap “Melakukan Mocking Metode Statis dan Konstruktor” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Testing Mastery: JUnit, Mockito & Integration Tests, upgrade ke CoddyKit PRO. Kursus Testing Mastery: JUnit, Mockito & Integration Tests mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Melakukan Mocking Metode Statis dan Konstruktor”?
Pelajari teknik tingkat lanjut untuk melakukan mock pada metode statis, kelas final, dan konstruktor menggunakan ekstensi Mockito seperti `mockito-inline`. Kamu berlatih Testing Mastery: JUnit, Mockito & Integration Tests dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Testing Mastery: JUnit, Mockito & Integration Tests?
Tidak diperlukan pengalaman sebelumnya. Testing Mastery: JUnit, Mockito & Integration Tests di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “Melakukan Mocking Metode Statis dan Konstruktor” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Testing Mastery: JUnit, Mockito & Integration Tests ini?
Ya. Setiap pelajaran Testing Mastery: JUnit, Mockito & Integration Tests menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Jawaban Khusus dan Panggilan Balik
- Melakukan Mocking Metode Statis dan Konstruktor
- Praktik Terbaik Mockito
- Menangkap Argumen dengan ArgumentCaptor