Soru Özel bir işlevi veya özel yöntemleri, alanları veya iç sınıfları olan bir sınıfı nasıl sınarım?
İç özel yöntemleri, alanları veya yuvalanmış sınıfları olan bir sınıfı nasıl sınama (xUnit kullanarak)? Ya da sahip olunan özel bir işlev iç bağlantı (
static C / C ++) veya özel bir (anonim) isim alanı?
Bir testi veya işlevi çalıştırmak için erişim düzenleyicisini değiştirmek sadece bir test yapmak için kötü görünüyor.
2268
Menşei
Cevaplar:
Bir çeşit mirasınız varsa Java uygulama ve yöntemlerin görünürlüğünü değiştiremezsiniz, özel yöntemleri test etmenin en iyi yolu kullanmaktır yansıma.
Dahili olarak almak / ayarlamak için yardımcıları kullanıyoruz
private ve
private static değişkenler yanı sıra çağırmak
private ve
private static yöntemleri. Aşağıdaki modeller özel yöntemler ve alanlar ile ilgili hemen hemen her şeyi yapmanıza izin verecektir. Tabi ki değişemezsin
private static final değişkenler yansıma yoluyla.
Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);
Ve alanlar için:
Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
Notlar:
1.
targetClass.getDeclaredMethod(methodName, argClasses) içine bakmanızı sağlar
private yöntemleri. Aynı şey için de geçerlidir
getDeclaredField.
2. The
setAccessible(true) özel kişilerle oynamak için gereklidir.
1417
Özel bir yöntemi test etmenin en iyi yolu başka bir kamu yöntemidir. Bu yapılamazsa, aşağıdaki koşullardan biri doğrudur:
- Özel yöntem ölü koddur
- Test ettiğiniz sınıfa yakın bir tasarım kokusu var.
- Test etmeye çalıştığınız yöntem gizli olmamalıdır
507
Bir sınıfta, özel yöntemleri doğrudan test etme gereği duyduğum kadar karmaşık olan özel yöntemlerim olduğunda, bu bir kod kokusu: Sınıfım çok karmaşık.
Bu gibi konulara değinmek için alışılagelen yaklaşımım, ilginç bitleri içeren yeni bir ders çıkarmaktır. Çoğunlukla, bu yöntem ve etkileştiği alanlar ve belki başka bir yöntem veya iki yeni bir sınıfa çıkarılabilir.
Yeni sınıf bu yöntemleri 'kamu' olarak sergiliyor, böylece birim testi için erişilebilir durumdalar. Yeni ve eski sınıflar artık hem orijinal sınıftan daha basit, hem de benim için harika (Ben işleri basit tutmalıyım, yoksa kaybolurum!).
İnsanların beyinlerini kullanmadan sınıflar oluşturmasını önermediğimi unutmayın! Buradaki nokta, iyi yeni sınıflar bulmanıza yardım etmek için birim test etme güçlerini kullanmaktır.
272
Kullandım yansıma Java için bunu geçmişte yapmak için ve bence bu büyük bir hataydı.
Kesinlikle konuşmalısın değil Özel yöntemleri doğrudan test eden birim testler olmak. Sen ne meli test olmak, sınıfın diğer nesnelerle sahip olduğu kamu sözleşmesidir; Bir nesnenin içsellerini asla doğrudan test etmemelisiniz. Başka bir geliştirici, sınıftaki kamu sözleşmesini etkilemeyen, sınıf için küçük bir iç değişiklik yapmak isterse, o zaman, çalışmasını sağlamak için yansıma tabanlı testinizi değiştirmelidir. Bunu bir proje boyunca tekrar tekrar yaparsanız, ünite testleri daha sonra kod sağlığının yararlı bir ölçümünü yapmayı bırakır ve geliştirme için bir engel olmaya ve geliştirme ekibine bir can sıkmaya başlar.
Bunun yerine, yazdığınız birim sınamalarının özel yöntemlerle kodun düzgün bir şekilde sağlanmasını sağlamak için Cobertura gibi bir kod kapsamı aracı kullanmanız önerilir. Bu şekilde, özel yöntemlerin neler yaptığını dolaylı olarak test edersiniz ve daha yüksek bir çeviklik seviyesini korursunuz.
229
Bu yazıda: JUnit ve SuiteRunner ile Özel Yöntemlerin Test Edilmesi (Bill Venners), temelde 4 seçeneğiniz var:
- Özel yöntemleri test etme.
- Yöntem paketi paketi verin.
- Yuvalanmış bir test sınıfı kullanın.
- Yansıma kullanın.
187
Genel olarak bir birim testi, bir sınıfın veya birimin genel arayüzünü kullanmak üzere tasarlanmıştır. Bu nedenle, özel yöntemler açık bir şekilde test etmeyi beklemediğiniz uygulama detayıdır.
96
Özel bir yöntemi test etmek istediğim iki örnek:
- Şifre çözme rutinleri - Ben istemem
Sadece görmek istedikleri herkese görünür hale getirmek istiyorum
sınama uğruna, başka herkes
şifresini çözmek için bunları kullanın. Ama onlar
kod için içsel, karmaşık,
ve her zaman işe yaraması gerekir (bariz istisna, çoğu durumda özel yöntemleri bile görmek için kullanılabilecek yansımadır)
SecurityManager bunu önlemek için yapılandırılmamış).
- SDK oluşturma topluluk için
tüketimi. İşte kamu alır bir
bu yana tamamen farklı anlam
tüm dünyanın görebileceği koddur
(sadece başvuruma dahil değil). Koydum
yapmazsam özel yöntemlere kod
SDK kullanıcılarının bunu görmesini istiyorum - I
Bunu sadece kod kokusu olarak görmüyorum
SDK programlama nasıl çalışır. Ama
Tabii ki hala test etmek zorundayım
özel yöntemler ve onlar nerede
SDK'mın işlevselliği aslında
hayatları.
Sadece "sözleşmeyi" test etme fikrini anlıyorum. Ancak, birinin kodu test etmediğini göremiyorum - kilometreniz değişebilir.
Bu yüzden benim tradeoff'um güvenlik ve SDK'mdan ödün vermek yerine JUnits'i yansıtma ile karmaşıklaştırmayı içeriyor.
56
Özel yöntemler, genel bir yöntemle çağrılır, bu nedenle, genel yöntemlerinizdeki girdiler, bu genel yöntemlerle çağrılan özel yöntemleri de test etmelidir. Bir kamu yöntemi başarısız olduğunda, bu özel yöntemde bir başarısızlık olabilir.
53
Kullandığım diğer bir yaklaşım ise, özel ya da korunan paketlemek için özel bir yöntemi değiştirmek ve daha sonra @VisibleForTesting Google Guava kütüphanesinin ek açıklaması.
Bu, bu yöntemin herhangi bir şekilde dikkatli kullanılmasını ve bir pakette bile doğrudan erişmemesini söyleyecektir. Ayrıca bir test sınıfının aynı pakette olması gerekmez fiziksel olarakama aynı pakette Ölçek Klasör.
Örneğin, test edilecek bir yöntem varsa
src/main/java/mypackage/MyClass.java o zaman test aramanız
src/test/java/mypackage/MyClassTest.java. Böylece test sınıfınızda test yöntemine erişebilirsiniz.
30
Eski kodları büyük ve ilginç sınıflarla test etmek için yazdığım bir özel (veya kamu) yöntemini test edebilmek genellikle çok faydalıdır. şimdi.
ben kullanıyorum junitx.util.PrivateAccessor- Java için paket. Özel yöntemlere ve özel alanlara erişmek için yararlı tek gömleklerin bir sürü.
import junitx.util.PrivateAccessor;
PrivateAccessor.setField(myObjectReference, "myCrucialButHardToReachPrivateField", myNewValue);
PrivateAccessor.invoke(myObjectReference, "privateMethodName", java.lang.Class[] parameterTypes, java.lang.Object[] args);
28