Kami mencoba merancang sistem kami agar dapat diuji dan di sebagian besar dikembangkan menggunakan TDD. Saat ini kami sedang mencoba menyelesaikan masalah berikut:
Di berbagai tempat, kita perlu menggunakan metode pembantu statis seperti ImageIO dan URLEncoder (keduanya API Java standar) dan berbagai perpustakaan lain yang sebagian besar terdiri dari metode statis (seperti perpustakaan Apache Commons). Tetapi sangat sulit untuk menguji metode-metode yang menggunakan kelas pembantu statis tersebut.
Saya punya beberapa ide untuk menyelesaikan masalah ini:
- Gunakan kerangka tiruan yang bisa mengejek kelas statis (seperti PowerMock). Ini mungkin solusi paling sederhana tetapi entah bagaimana rasanya menyerah.
- Buat kelas pembungkus instantiable di sekitar semua utilitas statis sehingga mereka dapat disuntikkan ke dalam kelas yang menggunakannya. Ini terdengar seperti solusi yang relatif bersih tapi saya khawatir kita akan akhirnya menciptakan banyak sekali kelas pembungkus itu.
- Ekstrak setiap panggilan ke kelas helper statis ini ke dalam fungsi yang dapat ditimpa dan menguji subkelas kelas yang sebenarnya ingin saya uji.
Tapi saya terus berpikir bahwa ini hanya harus menjadi masalah yang harus dihadapi banyak orang ketika melakukan TDD - jadi pasti sudah ada solusi untuk masalah ini.
Apa strategi terbaik agar kelas yang menggunakan pembantu statis ini dapat diuji?
sumber
Jawaban:
(Tidak ada sumber "resmi" di sini, saya khawatir - tidak seperti ada spesifikasi untuk cara menguji dengan baik. Hanya pendapat saya, yang semoga bermanfaat).
Ketika metode statis ini mewakili dependensi asli , buat pembungkus. Jadi untuk hal-hal seperti:
... masuk akal untuk membuat antarmuka.
Tetapi banyak metode di Apache Commons mungkin tidak boleh diejek / dipalsukan. Misalnya, ambil metode untuk bergabung bersama daftar string, menambahkan koma di antara mereka. Tidak ada gunanya mengejek ini - biarkan saja panggilan statis melakukan pekerjaan normal. Anda tidak ingin atau tidak perlu mengganti perilaku normal; Anda tidak berurusan dengan sumber daya eksternal atau sesuatu yang sulit untuk dikerjakan, itu hanya data. Hasilnya mudah ditebak dan Anda tidak akan pernah ingin menjadi sesuatu yang lain dari apa yang akan memberikan pula.
Saya menduga bahwa setelah menghapus semua panggilan statis yang benar-benar merupakan metode kenyamanan dengan hasil "murni" yang dapat diprediksi (seperti pengkodean base64 atau URL) daripada masuk ke kekacauan besar dependensi logis (seperti HTTP) Anda akan menemukan itu sepenuhnya praktis untuk melakukan hal yang benar dengan dependensi asli.
sumber
Ini jelas merupakan pertanyaan / jawaban, tetapi untuk apa nilainya saya pikir saya akan memasukkan dua sen saya. Dalam hal gaya TDD metode 2 jelas merupakan pendekatan yang mengikutinya ke surat itu. Argumen untuk metode 2 adalah bahwa jika Anda ingin mengganti implementasi salah satu kelas tersebut - katakan
ImageIO
perpustakaan yang setara - maka Anda bisa melakukannya sambil mempertahankan kepercayaan pada kelas yang memanfaatkan kode itu.Namun, seperti yang Anda sebutkan, jika Anda menggunakan banyak metode statis maka Anda akan berakhir dengan menulis banyak kode wrapper. Ini mungkin bukan hal buruk dalam jangka panjang. Dalam hal rawatan tentu ada argumen untuk ini. Secara pribadi saya lebih suka pendekatan ini.
Karena itu, PowerMock ada karena suatu alasan. Ini adalah masalah yang cukup terkenal bahwa pengujian ketika metode statis yang terlibat sangat menyakitkan, karena itu lahirnya PowerMock. Saya pikir Anda perlu mempertimbangkan pilihan Anda dalam hal berapa banyak pekerjaan yang akan dilakukan untuk membungkus semua kelas pembantu Anda vs menggunakan PowerMock. Saya tidak berpikir itu 'menyerah' untuk menggunakan PowerMock - Saya hanya merasa bahwa membungkus kelas memungkinkan Anda lebih fleksibel dalam proyek besar. Semakin banyak kontrak publik (antarmuka) Anda dapat memberikan pembersih pemisahan antara niat dan implementasi.
sumber
Sebagai referensi untuk semua yang juga berurusan dengan masalah ini dan menemukan pertanyaan ini saya akan menjelaskan bagaimana kami memutuskan untuk mengatasi masalah:
Kami pada dasarnya mengikuti jalur yang diuraikan sebagai # 2 (kelas pembungkus untuk utilitas statis). Tetapi kita hanya menggunakannya ketika terlalu rumit untuk menyediakan utilitas dengan data yang diperlukan untuk menghasilkan output yang diinginkan (yaitu ketika kita benar-benar harus mengejek metode).
Ini berarti kita tidak perlu menulis pembungkus untuk utilitas sederhana seperti Apache Commons
StringEscapeUtils
(karena string yang mereka butuhkan dapat dengan mudah disediakan) dan kita tidak menggunakan ejekan untuk metode statis (jika kita pikir kita mungkin perlu waktu untuk menulis kelas pembungkus dan kemudian mengejek instance pembungkus).sumber
Saya akan menguji kelas-kelas ini menggunakan Groovy . Groovy mudah ditambahkan ke proyek Java apa pun. Dengan itu, Anda dapat mengejek metode statis dengan mudah. Lihat Mengejutkan Metode Statis menggunakan Groovy sebagai contoh.
sumber
Saya bekerja untuk perusahaan asuransi besar dan kode sumber kami mencapai 400MB file java murni. Kami telah mengembangkan seluruh aplikasi tanpa memikirkan TDD. Dari Januari tahun ini kami mulai dengan pengujian junit untuk setiap komponen individu.
Solusi terbaik di departemen kami adalah menggunakan objek Mock pada beberapa metode JNI yang dapat diandalkan sistem (ditulis dalam C) dan karena itu Anda tidak dapat memperkirakan hasil setiap kali pada setiap OS. Kami tidak memiliki pilihan lain selain menggunakan kelas yang diolok-olok dan implementasi spesifik dari metode JNI khusus untuk tujuan menguji setiap modul aplikasi untuk setiap OS yang kami dukung.
Tapi itu sangat cepat dan sejauh ini sudah berfungsi dengan baik. Saya merekomendasikannya - http://www.easymock.org/
sumber
Objek berinteraksi satu sama lain untuk mencapai tujuan, ketika Anda memiliki objek yang sulit untuk diuji karena lingkungan (titik akhir layanan web, lapisan dao mengakses DB, pengendali menangani parameter permintaan http) atau Anda ingin menguji objek Anda secara terpisah, lalu Anda mengejek benda-benda itu.
perlunya mengolok-olok metode statika adalah bau yang tidak sedap, Anda harus mendesain aplikasi Anda lebih Berorientasi Objek, dan unit pengujian utilitas metode statis tidak menambah banyak nilai pada proyek, kelas wrapper adalah pendekatan yang baik tergantung pada situasinya, tetapi cobalah untuk menguji objek-objek yang menggunakan metode statis.
sumber
Terkadang saya menggunakan opsi 4
Sesuatu seperti ini.
Apa yang saya sukai dari pendekatan ini adalah ia membuat metode utilitas tetap statis, yang terasa benar bagi saya ketika saya mencoba menggunakan kelas di seluruh kode.
sumber