【问题标题】:Set Value of Private Static Field设置私有静态字段的值
【发布时间】:2013-03-18 21:10:43
【问题描述】:

我想使用反射设置私有字段的值以进行单元测试。

问题是,该字段是静态的。

这是我的工作内容:

/**
   * 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;
  }

我意识到这可能已经在 SO 上得到了回答,但我的搜索没有出现...

【问题讨论】:

  • 显而易见的答案是“Jasus,不要改变其他类的静态或私有数据。”您可以尝试从上方进行参数化。
  • 如果您使用的是 spring,您可以在私有字段上设置 @Autowired,然后如果您需要用模拟替换该实例,您需要使用测试方法中的反射来更改它

标签: java unit-testing reflection


【解决方案1】:

基本上问题在于您的实用程序方法,它假设您有一个实例。设置私有静态字段相当容易 - 它与实例字段的过程完全相同,除了您将 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();
    }
}

【讨论】:

  • 我认为单元测试不应该像你所说的那样推动我们在生产类中做任何事情:我会创建一个包级方法
【解决方案2】:

只需将null 传递给对象实例参数。所以:

field.set(null, p_fieldValue);

这将让您设置静态字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-13
    • 2020-11-12
    • 2014-06-19
    • 2012-09-29
    • 2017-02-28
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多