Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi · Pelajaran

Mock Kaedah Statik dan Pembina

Terokai teknik lanjutan untuk membuat mock bagi kaedah statik, kelas muktamad dan pembina menggunakan sambungan Mockito seperti `mockito-inline`.

Pelajaran 2 daripada 411 langkah

Mock Kaedah Statik dan Pembina ialah pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi merangkumi sejumlah 4 pelajaran.

Melangkaui Mock Biasa

Selamat datang! Setakat ini, anda telah mempelajari cara memock antara muka dan kelas biasa menggunakan Mockito. Tetapi bagaimana pula dengan bahagian kod yang sukar diuji?

Kadangkala, anda menemui kaedah statik, kelas muktamad atau panggilan pembina secara langsung (new MyObject()) dalam kod yang ingin anda uji. Mockito standard tidak dapat mengendalikan perkara ini secara langsung.

Apabila Mock Tradisional Gagal

Mengapakah kita perlu memock perkara ini?

  • Kaedah utiliti statik: Sering digunakan untuk tugas umum, tetapi sukar diasingkan jika mempunyai kesan sampingan atau kebergantungan luaran.
  • Kelas/kaedah muktamad: Tidak boleh dijadikan subkelas atau ditindih, menyebabkan pemockan berasaskan proksi tradisional mustahil.
  • Panggilan pembina (new): Penciptaan objek secara langsung dalam sesuatu kaedah menyukarkan penyuntikan mock sebagai gantinya.

Memock perkara ini membantu anda mengasingkan kod yang sedang diuji, termasuk dalam sistem yang kompleks atau legasi.

Memperkasa Mockito

Untuk mengatasi batasan ini, Mockito menawarkan keupayaan lanjutan melalui pencipta mock sebaris, yang sering dirujuk sebagai mockito-inline.

Ciri ini menggunakan manipulasi kod bait untuk "menulis semula" kelas semasa masa jalan, membolehkan Mockito memock perkara yang biasanya tidak boleh dimock, seperti kaedah statik, kelas muktamad dan juga pembina.

Ini alat yang berkuasa, tetapi gunakannya dengan teliti!

Menyediakan Projek Anda

Untuk versi Mockito 3.4.0 dan yang lebih baharu, pencipta mock sebaris selalunya didayakan secara lalai atau tersedia hanya dengan menggunakan kebergantungan mockito-core standard.

Jika anda menggunakan versi yang lebih lama atau menghadapi masalah, anda mungkin perlu mengisytiharkan mockito-inline secara jelas. Bagi kebanyakan persediaan moden, pastikan anda hanya menggunakan versi mockito-core yang terkini.

Beginilah rupa build.gradle anda mungkin kelihatan:

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'
}

Memock Pembantu Statik

Untuk memock kaedah statik, Mockito menyediakan antara muka MockedStatic. Anda mencipta konteks mock menggunakan Mockito.mockStatic() dalam blok try-with-resources. Ini memastikan mock aktif hanya sepanjang tempoh blok tersebut.

Mari lihat contoh dengan kelas utiliti:

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());
    }
}

Menyemak Interaksi Statik

Sama seperti mock biasa, anda boleh mengesahkan interaksi dengan kaedah statik. Gunakan kaedah verify() pada objek MockedStatic anda.

Ini memastikan kod yang sedang diuji memanggil kaedah statik seperti yang dijangka, dengan argumen dan bilangan panggilan yang betul.

Perhatikan Mockito.times(1) dalam contoh sebelumnya untuk menyemak bilangan panggilan.

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
    }
}

Mengendalikan Kelas Muktamad

Pencipta mock mockito-inline juga membolehkan anda memock kelas muktamad dan kaedah muktamad. Ini amat berguna apabila berurusan dengan pustaka pihak ketiga atau kod legasi yang reka bentuk kelasnya sukar diubah.

Anda memock kelas muktamad sama seperti kelas biasa: 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");
    }
}

Memintas Objek Baharu

Bagaimana jika kod anda mencipta objek baharu secara langsung menggunakan new MyObject()? MockedConstruction membolehkan anda memintas panggilan ini dan memulangkan tika mock sebagai ganti tika sebenar.

Ini penting untuk menguji kelas yang mengurus kebergantungannya secara dalaman dan bukannya menerimanya melalui suntikan kebergantungan.

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
    }
}

Gunakan Dengan Berhati-hati

Walaupun berkuasa, pemockan kaedah statik dan pembina boleh menjadi petunjuk bahawa reka bentuk sukar diuji.

  • Bau Reka Bentuk: Kebergantungan yang terlalu besar pada mock ini mungkin menunjukkan bahawa kelas anda terlalu berganding rapat atau tidak mengikut prinsip suntikan kebergantungan.
  • Kebolehbacaan: Ujian yang menggunakan mock lanjutan ini mungkin lebih sukar difahami dan diselenggara.
  • Bila perlu digunakan: Paling sesuai untuk kod legasi, pustaka pihak ketiga atau keadaan apabila pemfaktoran semula tidak dapat dilakukan serta-merta. Utamakan pemfaktoran semula untuk kebolehujian apabila boleh!

Semakan Pemockan Lanjutan

Manakah antara pernyataan berikut tentang mockito-inline dan teknik pemockan lanjutan yang BENAR?

Imbas Kembali Pemockan Lanjutan

Syabas! Anda telah meneroka teknik Mockito lanjutan:

  • Pencipta mock mockito-inline membolehkan pemockan kaedah statik, kelas muktamad dan pembina.
  • MockedStatic membolehkan anda membuat stub dan mengesahkan panggilan kaedah statik dalam skop yang ditentukan.
  • MockedConstruction membantu memintas dan menggantikan objek yang dicipta melalui kata kunci new.

Alat ini berkuasa untuk menguji kod yang mencabar, tetapi ingatlah untuk mempertimbangkan corak reka bentuk yang mendasarinya. Seterusnya, anda akan mempelajari amalan terbaik Mockito!

Percuma untuk bermula

Pelajari Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
12
Pelajaran
48

Soalan Lazim

Adakah pelajaran “Mock Kaedah Statik dan Pembina” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi, termasuk “Mock Kaedah Statik dan Pembina”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Mock Kaedah Statik dan Pembina”?

Terokai teknik lanjutan untuk membuat mock bagi kaedah statik, kelas muktamad dan pembina menggunakan sambungan Mockito seperti `mockito-inline`. Anda berlatih Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Mock Kaedah Statik dan Pembina” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi ini?

Ya. Setiap pelajaran Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Jawapan Tersuai dan Panggilan Balik
  2. Mock Kaedah Statik dan Pembina
  3. Amalan Terbaik Mockito
  4. Menangkap Argumen dengan ArgumentCaptor
← Kembali ke Penguasaan Pengujian: JUnit, Mockito & Ujian Integrasi