我如何模拟正在内联初始化的字段变量?
EG
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
在这里,我想在测试方法时测试person.someMethod() - Test#testMethod。
我需要模拟person变量的初始化。任何线索?
编辑:我不允许修改Person类。
Mockito附带一个助手类来为您节省一些反射锅炉板代码:
import org.mockito.internal.util.reflection.Whitebox;
//...
@Mock
private Person mockedPerson;
private Test underTest;
// ...
@Test
public void testMethod() {
Whitebox.setInternalState(underTest, "person", mockedPerson);
// ...
}
更新:不幸的是,mockito团队决定在Mockito 2中使用remove the class。所以你回来编写自己的反射样板代码,使用另一个库(例如Apache Commons Lang),或者只是窃取Whitebox类(它是MIT licensed)。
更新2:JUnit 5附带了自己的ReflectionSupport和AnnotationSupport类,这些类可能很有用,可以避免您拉入另一个库。
聚会很晚,但我被这里的朋友打扰了。事情不是使用PowerMock。这适用于最新版本的Mockito。
Mockito带有这个org.mockito.internal.util.reflection.FieldSetter
。
它基本上做的是帮助您使用反射修改私有字段。
这是你如何使用它 -
@Mock
private Person mockedPerson;
private Test underTest;
// ...
@Test
public void testMethod() {
FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
// ...
verify(mockedPerson).someMethod();
}
这样,您可以传递模拟对象,然后再进行验证。
参考:
https://www.codota.com/code/java/methods/org.mockito.internal.util.reflection.FieldSetter/set
我已经找到了这个问题的解决方案,我忘了在这里发布。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {
@Mock
Person person;
@Test
public void testPrintName() throws Exception {
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Test test= new Test();
test.testMethod();
}
}
该解决方案的关键点是:
@RunWith(PowerMockRunner.class)
Test.class
操纵私人领域:@PrepareForTest({ Test.class })
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
如果您使用Spring Test,请尝试org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
以下代码可用于在REST客户端模拟中初始化映射器。 mapper
字段是私有的,需要在单元测试设置期间设置。
import org.mockito.internal.util.reflection.FieldSetter;
new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
使用@ Jarda指南,如果需要为所有测试设置相同的值,则可以定义它:
@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}
但请注意,应谨慎处理将私有值设置为不同的情况。如果他们是私人的,出于某种原因。
例如,我使用它来改变单元测试中睡眠的等待时间。在实际例子中,我想睡10秒,但在单元测试中我很满意,如果它是立即的。在集成测试中,您应该测试实际值。