Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用getter时,最终字段的PowerMock setInternalState不工作_Java_Unit Testing_Mocking_Powermock_Powermockito - Fatal编程技术网

Java 使用getter时,最终字段的PowerMock setInternalState不工作

Java 使用getter时,最终字段的PowerMock setInternalState不工作,java,unit-testing,mocking,powermock,powermockito,Java,Unit Testing,Mocking,Powermock,Powermockito,我有一节这样的课 public class ExampleClass { private final String finalString = "final"; public String getFinalString() { return finalString; } } 这是我的示例测试类,它试图改变finalString public class ExampleClassTest { private ExampleClass exampl

我有一节这样的课

public class ExampleClass {
    private final String finalString = "final";

    public String getFinalString() {
        return finalString;
    }
}
这是我的示例测试类,它试图改变
finalString

public class ExampleClassTest {
    private ExampleClass exampleClass = new ExampleClass();

    @Before
    public void setUp() throws Exception {
        Whitebox.setInternalState(exampleClass,"finalString","mocked");
    }

    @Test
    public void name() throws Exception {
        assertEquals("mocked", exampleClass.getFinalString()); //failing 
    }
}
但在这里,我的主张失败了。
exampleClass.getFinalString()
的值声明为
“final”

但是,当我在断言行调试代码并检查字段
finalString
的值时,或者当我尝试使用反射(下面的代码)获取字段
finalString
的值时,它会显示
“mocked”

我的反射代码

Field finalStringField = exampleClass.getClass().getDeclaredField("finalString");
finalStringField.setAccessible(true);
assertEquals("mocked",finalStringField.get(exampleClass)); //passing
有人明白这里的诀窍吗

附言:我在最后一场比赛中的表现确实很奇怪。请忽略它

而且,即使我加上

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExampleClass.class)

在我的测试类的顶部,相同的结果

确保您使用的是哪个白盒,您应该使用PowerMock one,只需将白盒的行更新为

PowerMock.Whitebox.setInternalState(exampleClass, "finalString", "mocked");
,如果上述方法不起作用,请尝试模拟对象并调用real方法:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExampleClass.class)
public class ExampleClassTest {

    private ExampleClass exampleClass;

    @Before
    public void setUp() throws Exception {
        exampleClass = PowerMock.mock(ExampleClass.class, Mocktio.CALL_REAL_METHOD);
        PowerMock.Whitebox.setInternalState(exampleClass, "finalString", "mocked");
    }

    @Test
    public void name() throws Exception {
        assertEquals("mocked", exampleClass.getFinalString());
    }
}

我自己找到了答案。获取要断言的值的正确方法如下所示。为此,我们需要使用
Whitebox.getInternalState
Whitebox.getField
方法之一

因此,它将是以下之一

assertEquals(“mocked”,Whitebox.getInternalState(exampleClass,“finalString”)


assertEquals(“mocked”,Whitebox.getField(exampleClass.getClass(),“finalString”).get(exampleClass))

@PrepareForTest(ExampleClass.class)
ExampleClass ExampleClass=newexampleClass()是相互矛盾的。你是想嘲弄它还是不想?如果您对其进行模拟,模拟将没有用于反射的字段,因此您的测试将失败。你需要使用真实的东西。此外,你正在以一种奇怪的方式使用
setUp
,这毫无意义。您的测试应该包括测试代码本身和断言。这样做,您基本上永远不会添加第二个测试。重复我的话,请仔细阅读:您不能对模拟或代理类(例如spy)上的字段使用反射,因为这些类将不具有该字段。删除所有的模仿和间谍,以及诸如此类的东西。@Michael,所以我的代码不包括任何模仿或间谍权利。所以,如果我只是删除顶部的两个注释,让事情更清楚,可以吗?你应该这样做,是的。我不知道它的具体细节,但是当您执行
PrepareForTest
时,PowerMock的工作方式是在类装入器装入类时修改类的字节码。因此,对修改后的类的反射很可能会以一些奇怪的方式失败。与我的问题第一个相同的结果,检查是否使用PowerMock.Whitebox one,而不是Mocktio.Whitebox。是的,但我忘记了后缀,它是以
ito
结尾还是不让我在本地