2014-04-18 13 views
20

Bu testi geçmek için yapılması gereken mutlak minimum alay nedir?PowerMock: özel statik final değişkenini atayın, somut bir örnek

kodu:

class PrivateStaticFinal { 
    private static final Integer variable = 0; 
    public static Integer method() { return variable + 1; } 
} 

testi

:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(PrivateStaticFinal.class) 
class PrivateStaticFinalTest { 
    @Test 
    public void testMethod() { 
     //TODO PrivateStaticFinal.variable = 100 
     assertEquals(PrivateStaticFinal.method(), 101); 
    } 
} 

related: Mock private static final variables in the testing class (net yanıt)

+1

Bu istatistiklerin hepsi aynı sınıfı zorlaştırıyor. Girdiğim tüm sorunlar, bir sınıfı test etmeye çalışırken diğer yerlerden istatistik kullanıyor. Test etmeye çalıştığınız sınıfın kısmi kısımlarıyla dalga geçmek sadece kötü görünüyor. Test ettiğin sınıfa asla alay etmemelisin, sadece bağlı olduğu şeyler. – Walls

cevap

34

Yasal Uyarı: avcılık bir sürü sonra etrafında çeşitli iş parçacığı üzerinde buldum Bir cevap. Yapılabilir, ancak genel konsensüs çok güvenli ama nasıl SADECE BİRİM TESTLERİNDE yapıyoruz görünce olmadığıdır, sana bu riskleri :)


cevap alaycı değil kabul düşünüyorum Çoğu Mocking bir finale girmenize izin vermez. Cevabı biraz daha "hacky", Java çağırırken özel alanı değiştirdiğiniz yerde çekirdek java.lang.reflect.Field ve java.lang.reflect.Modifier sınıfları (yansıma). this answer'a baktığımda, probleminizi çözen alay gerekmeden testinizin geri kalanını bir araya getirebildim.

Bu yanıtla ilgili sorun, variable'u değiştirmeye çalışırken NoSuchFieldException içine koşuyordum. Bunun yardımı, özel ve herkese açık olmayan bir alana nasıl erişileceği hakkında another post numaralı telefondan alınmıştır.

Yansıma/Alan Manipülasyon Açıklaması:

son işleyemez alaycı beri bunun yerine yapıyor sonunda hangi alanda kendisini kök içine hekleniyor. Field manipülasyonlarını (yansıma) kullandığımızda, bir sınıfın/nesnenin içindeki spesifik değişkeni arıyoruz. Bir kez Java bulursa, "değişkenleri" alırız, bu değişkene hangi kısıtlamaların/kuralların final, static, private, public vb. Gibi olduğunu söyleriz. Doğru değişkeni buluruz ve daha sonra bu kodun erişilebilir olduğunu söyleriz. Bu değiştiricileri değiştirmemize izin veriyor. Kökündeki "erişimi" değiştirdiğimizde, onu manipüle etmemize izin verdiğimizde, "son" kısmını değiştiriyoruz. Daha sonra değeri değiştirebilir ve ihtiyacımız olan her şeye ayarlayabiliriz.

Basitçe ifade etmek gerekirse, final ürününün özelliklerini kaldırarak, daha sonra final artık olmadığı için değeri değiştirmemize izin vermek için değişkeni değiştiriyoruz. Bu konuda daha fazla bilgi için, check out the post where the idea came from.

nedenle tüm Alacağınız yeni SÜPER CEVAP içine ...

// Mark the field as public so we can toy with it 
field.setAccessible(true); 
// Get the Modifiers for the Fields 
Field modifiersField = Field.class.getDeclaredField("modifiers"); 
// Allow us to change the modifiers 
modifiersField.setAccessible(true); 
// Remove final modifier from field by blanking out the bit that says "FINAL" in the Modifiers 
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
// Set new value 
field.set(null, newValue); 

bu birleştirerek biz manipüle etmek istediğiniz değişkeni geçmek adım adım ve.

@RunWith(PowerMockRunner.class) 
@PrepareForTest() 
class PrivateStaticFinalTest { 
    @Test 
    public void testMethod(){ 
     try { 
     setFinalStatic(PrivateStaticFinal.class.getDeclaredField("variable"), Integer.valueOf(100)); 
     } 
     catch (SecurityException e) {fail();} 
     catch (NoSuchFieldException e) {fail();} 
     catch (Exception e) {fail();} 
     assertEquals(PrivateStaticFinal.method(), Integer.valueOf(101)); 
    } 

    static void setFinalStatic(Field field, Object newValue) throws Exception { 
     field.setAccessible(true); 
     // remove final modifier from field 
     Field modifiersField = Field.class.getDeclaredField("modifiers"); 
     modifiersField.setAccessible(true); 
     modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
     field.set(null, newValue); 
    } 
} 

yukarıdaki çözüm bildirerek ve aynı zamanda sabit başlatılıyor statik block.When başlatıldıktan bu sabitleri için sadece çalışacak Güncelleme, bu başına gelebilecek derleyici inlines o noktada Orijinal değere yapılan herhangi bir değişiklik göz ardı edilir.

+0

'Field modifiersField = Field.class.getDeclaredField ("modifiers"); değiştiricilerField.setAccessible (true); değiştiricilerField.setInt (field, field.getModifiers() & ~ Değiştirici.FINAL); field.set (null, newValue); 'yapar? –

+0

Cevabı biraz daha fazla açıklamanın yanı sıra, değişkenin kendisinin içine girmemize ve nihai kaliteyi ortadan kaldırmamıza izin veren "değiştiricileri" "değiştirecek" fikrinin kaynağı olan orijinal makaleyle bir bağlantıyı da düzenledik. onun. – Walls

+0

Teşekkürler! Test kodunun kaynak koduna hala uymasını istiyorum, böylece bir 'modifiersField.setInt (alan, alan.getModifiers() & Modifier.FINAL); modifiersField.setAccessible (false); 'İstediğimiz değeri ayarladıktan sonra çalışır. yani "yap/geri al" bir şey. –

İlgili konular