Kelas pengujian unit yang memiliki fungsi online

23

Ketika unit menguji fungsi kelas yang memiliki fungsi pribadi yang memerlukan fungsionalitas online. Bagaimana cara mengujinya?

Sebagai contoh:

public class Foo
{
    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        CloudService c = new CloudService();
        int oval = c.getValueFromService();
        return oval;
    }
}

Jika saya menguji fungsi: 'methodA ()' ia akan mencoba menggunakan 'goOnlineToGetVal ()' yang pada gilirannya akan mencoba online, jika tes ini dilakukan tanpa fungsionalitas. Bagaimana saya bisa menjangkau sekitar 100% cakupan Kelas tanpa online?

Ben Crazed Up Euden
sumber
Apakah metode Anda hanya memanggil awan api, atau apakah itu melakukan pekerjaan tambahan juga?
Winston Ewert
4
Injeksi Ketergantungan?
PhaDaPhunk

Jawaban:

76

new CloudService()

Dan ini masalahnya.

Desain OO modern merekomendasikan bahwa ketergantungan semacam ini dilewatkan daripada dibangun secara langsung. Ini dapat diteruskan ke fungsi itu sendiri, atau ke kelas pada waktu konstruksi. Itu juga bisa diambil atau diagregasi oleh wadah Inversion of Control jika kompleksitas semacam itu diperlukan.

Pada saat itu, menjadi sangat sepele untuk memberikan layanan tiruan / palsu untuk memberi Anda data "online" Anda selama pengujian. Lebih baik lagi, ini memungkinkan perangkat lunak Anda menjadi cukup fleksibel, sehingga Anda dapat dengan cepat beradaptasi jika beberapa klien (pemerintah?) Datang dan tidak ingin menggunakan cloud untuk nilai-nilai mereka. Atau Anda ingin membuang satu penyedia cloud untuk yang lain. Atau...

Telastyn
sumber
7
Saya pikir saya baru saja jauh lebih dekat untuk memahami apa Injeksi Ketergantungan sih.
marczellm
Di mana tempat terbaik untuk membuat semua instance yang dibutuhkan aplikasi saya? Sedekat mungkin dengan bagian atas aplikasi saya? Anda hanya dapat menerapkan injeksi ketergantungan sejauh ini; pada titik tertentu Anda harus membuat instance sendiri alih-alih menjadikannya sebagai argumen.
Paul
3
@ Paul - Tergantung. Dalam pengalaman saya, aplikasi sangat sering terlihat seperti pohon biner - satu kelas / fungsi / modul menempelkan keduanya untuk memberikan beberapa perilaku yang lebih kompleks. Salah satu kelas "lem" adalah kelas yang menentukan implementasi konkret, yang pada gilirannya digunakan oleh sesuatu di atas yang menempelkannya dengan sesuatu yang lain, yang pada gilirannya ... sampai Anda akhirnya sampai ke titik masuk Anda yang menempelkan potongan-potongan besar bersama-sama koheren. Tempat "terbaik" adalah tempat yang memungkinkan kode Anda melakukan apa yang perlu dilakukan, tanpa membuatnya atau tahu tentang hal-hal yang seharusnya tidak. Itu akan bervariasi.
Telastyn
2
@ Paul Biasanya aplikasi Anda dibagi antara "perpustakaan", yang langsung diuji dan harus menggunakan injeksi ketergantungan semacam ini, dan kode khusus aplikasi. Yang terakhir biasanya bermuara pada beberapa GUI, beberapa layanan web atau antarmuka baris perintah yang secara langsung memanggil perpustakaan dengan data yang disediakan pengguna. Pada dasarnya, kode khusus aplikasi akan membuat implementasi konkret yang diharapkan oleh pustaka yang disuntikkan ketergantungan.
Darkhogg
@ Paul Lihatlah wadah IoC seperti Castle Windsor, StructureMap, Ninject dan Unity. Mereka bukan satu-satunya cara untuk melakukan injeksi ketergantungan, tetapi mereka bisa sangat informatif dalam hal berpikir tentang membangun grafik objek, dari atas ke bawah
Ben Aaronson
37

Saya akan menerapkannya seperti ini:

public class Foo
{
    private ICloudService cloudService;

    public Foo(ICloudService s)
    {
       cloudService=s;
    }

    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        int oval = cloudService.getValueFromService();
        return oval;
    }
}

Antarmuka ICloudServicedapat diimplementasikan dengan tiruan untuk pengujian, atau dengan layanan cloud "nyata". Saat instantiasi new CloudService()wajib untuk setiap panggilan getValueFromService, atau CloudServiceberasal dari API pihak ke-3 yang tidak dapat diubah, terapkan pembungkus, yang berasal dari, ICloudServicedan lakukan panggilan yang sesuai.

Doc Brown
sumber
1
Ini jelas cara untuk pergi. Ada pustaka kelas yang dapat mengejek antarmuka yang memberi Anda kendali penuh terhadap tes.
Greg Burghardt