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
结尾还是不让我在本地