2010-07-13 13 views
33

मैं इकाई परीक्षण के लिए प्रतिबिंब का उपयोग करके एक निजी क्षेत्र का मूल्य निर्धारित करना चाहता हूं।निजी स्टेटिक फ़ील्ड का सेट वैल्यू

समस्या यह है कि वह क्षेत्र स्थैतिक है।

/** 
    * Use to set the value of a field you don't have access to, using reflection, for unit testing. 
    * 
    * Returns true/false for success/failure. 
    * 
    * @param p_instance an object to set a private field on 
    * @param p_fieldName the name of the field to set 
    * @param p_fieldValue the value to set the field to 
    * @return true/false for success/failure 
    */ 
    public static boolean setPrivateField(final Object p_instance, final String p_fieldName, final Object p_fieldValue) { 
    if (null == p_instance) 
     throw new NullPointerException("p_instance can't be null!"); 
    if (null == p_fieldName) 
     throw new NullPointerException("p_fieldName can't be null!"); 

    boolean result = true; 

    Class<?> klass = p_instance.getClass(); 

    Field field = null; 
    try { 
     field = klass.getDeclaredField(p_fieldName); 

     field.setAccessible(true); 
     field.set(p_instance, p_fieldValue); 

    } catch (SecurityException e) { 
     result = false; 
    } catch (NoSuchFieldException e) { 
     result = false; 
    } catch (IllegalArgumentException e) { 
     result = false; 
    } catch (IllegalAccessException e) { 
     result = false; 
    } 

    return result; 
    } 

मैं इस शायद पहले से ही इतने पर जवाब दिया गया है, लेकिन मेरे खोज से नहीं था एहसास ...

+3

स्पष्ट उत्तर है "जसस, अन्य वर्गों की सांख्यिकी या निजीकरण को मत बदलें।" आप ऊपर से पैरामीटरेटेशन का प्रयास कर सकते हैं। –

+0

यदि आप वसंत का उपयोग कर रहे हैं तो आप एक निजी क्षेत्र पर @Autowired सेट कर सकते हैं, फिर यदि आपको उस उदाहरण को एक नकली के साथ प्रतिस्थापित करने की आवश्यकता है तो आपको परीक्षण विधि –

उत्तर

38

असल समस्या है:

यहाँ मैं क्या से काम कर रहा हूँ है आपकी उपयोगिता विधि, जो मानती है कि आपके पास एक उदाहरण है। एक निजी स्थैतिक क्षेत्र को सेट करना उचित रूप से आसान है - यह उदाहरण के रूप में null निर्दिष्ट करने के अलावा, एक उदाहरण फ़ील्ड के लिए बिल्कुल वही प्रक्रिया है। दुर्भाग्य से आपकी उपयोगिता विधि कक्षा प्राप्त करने के लिए उदाहरण का उपयोग करती है, और इसे गैर-शून्य होने की आवश्यकता होती है ...

मैं टॉम की चेतावनी गूंजता हूं: ऐसा मत करो। यदि यह एक वर्ग है कि आप अपने नियंत्रण में है, मैं एक पैकेज के स्तर का विधि बनाएंगे:

void setFooForTesting(Bar newValue) 
{ 
    foo = newValue; 
} 

हालांकि, यहां एक पूरा नमूना है आप सच में, सच प्रतिबिंब के साथ सेट करना चाहते हैं:

import java.lang.reflect.*; 

class FieldContainer 
{ 
    private static String woot; 

    public static void showWoot() 
    { 
     System.out.println(woot); 
    } 
} 

public class Test 
{ 
    // Declared to throw Exception just for the sake of brevity here 
    public static void main(String[] args) throws Exception 
    { 
     Field field = FieldContainer.class.getDeclaredField("woot"); 
     field.setAccessible(true); 
     field.set(null, "New value"); 
     FieldContainer.showWoot(); 
    } 
} 
+8

से प्रतिबिंब का उपयोग करके इसे बदलने की आवश्यकता है, मुझे लगता है कि इकाई परीक्षण हमें करने के लिए धक्का नहीं देना चाहिए उत्पादन वर्गों में कुछ भी जो आप बताते हैं: मैं एक पैकेज स्तर विधि बनाउंगा –

5

ऑब्जेक्ट-इंस्टेंस तर्क के लिए बस null पास करें। तो:

field.set(null, p_fieldValue); 

यह आपको स्थैतिक क्षेत्र सेट करने देगा।

संबंधित मुद्दे