【问题标题】:PowerMock testing - set static field of classPowerMock 测试 - 设置类的静态字段
【发布时间】:2011-07-20 02:25:29
【问题描述】:

我很难找到设置类的静态字段的方法。基本上是这样的:

public class Foo{
    // ...
    private static B b = null;
}

其中 B 是另一个类。

除了setInternalStateFromContext(),还有什么方法可以在 PowerMock 中做到这一点?使用上下文类方法设置一个字段似乎有点矫枉过正。

谢谢。

【问题讨论】:

    标签: junit static mocking powermock


    【解决方案1】:
    Whitebox.setInternalState(Foo.class, "FIELD_NAME", "value");
    

    【讨论】:

      【解决方案2】:

      这里我将为“android.os.Build.VERSION.RELEASE”设置值,其中 VERSION 是类名,RELEASE 是最终的静态字符串值。

      如果基础字段是最终字段,则方法抛出 IllegalAccessException 除非 setAccessible(true) 成功 这个字段和这个字段是非静态的,使用field.set()方法时需要添加NoSuchFieldException

      @RunWith(PowerMockRunner.class)
      @PrepareForTest({Build.VERSION.class})
      public class RuntimePermissionUtilsTest {
      @Test
      public void hasStoragePermissions() throws IllegalAccessException, NoSuchFieldException {
          Field field = Build.VERSION.class.getField("RELEASE");
          field.setAccessible(true);
          field.set(null,"Marshmallow");
       }
      }
      

      现在字符串 RELEASE 的值将返回“Marshmallow”。

      【讨论】:

        【解决方案3】:

        试试这个:

        @RunWith(PowerMockRunner.class)
        @PrepareForTest({Foo.class})
        public class FooTest {
        
            @Test
            public void shouldMockPrivateStaticField() throws IllegalAccessException {
                // given
                Foo foo = new Foo();
                Field field = PowerMockito.field(Foo.class, "b");
                field.set(Foo.class, mock(B.class));
        

        不适用于基元和基元包装器。

        【讨论】:

        • 这实际上对我有用,我建议的唯一更改是:field.set(foo, mock(B.class));
        【解决方案4】:

        您可以使用getAllStaticFields 并尝试设置它们

        例子:

        YourFieldClass newValue;
        final Set<Field> fields = Whitebox.getAllStaticFields(YourClass.class);
                for (final Field field : fields) {
                    if (YourFieldClass.class.equals(field.getType())) { // or check by field name
                        field.setAccessible(true);
                        field.set(YourClass.class, newValue);
                    }       }
        

        【讨论】:

        【解决方案5】:
        Whitebox.setInternalState(Foo.class, b);
        

        只要您设置了一个非空值,并且如果只有一个类为B 的字段就可以工作。如果您不能依赖这种奢侈,则必须提供字段名称并将null 转换为您要设置的类型。在这种情况下,您需要编写如下内容:

         Whitebox.setInternalState( Foo.class, "b", (B)null );
        

        【讨论】:

          【解决方案6】:

          你只需这样做:

          Whitebox.setInternalState(Foo.class, b);
          

          其中 b 是您要设置的 B 的实例。

          【讨论】:

          • 你想为'b'设置的值只是setInternalState()的另一个参数吗?
          • 是的,它是第二个参数。例如。 B 新 = B(); Whitebox.setInternalState(Foo.class, b);
          • 只要您设置了一个非空值,它就可以工作。如果只有一个字段属于 b。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多