Mockito:模拟私有字段初始化

uyhoqukh  于 2022-12-18  发布在  其他
关注(0)|答案(9)|浏览(352)

如何模拟一个正在内联初始化的字段变量?

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

这里我想在测试Test.testMethod()方法的时候模拟person.someMethod(),我需要模拟person变量的初始化。

**编辑:**不允许修改Person类。

yftpprvb

yftpprvb1#

Mockito附带了一个helper类,可以为您节省一些反射代码:

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自带了ReflectionSupportAnnotationSupport类,这些类可能很有用,使您不必再调用另一个库。

kuarbcqp

kuarbcqp2#

如果您使用Spring测试,请尝试 *org.springframework.test.util.反射测试工具 *

ReflectionTestUtils.setField(testObject, "person", mockedPerson);
cyvaqqii

cyvaqqii3#

聚会很晚了,但是我在这里被击中了,得到了一个朋友的帮助。问题是不要使用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();
}

这样,您可以传递一个模拟对象,然后在以后验证它。
Here为基准电压源。

tf7tbtn2

tf7tbtn24#

我已经找到了这个问题的解决方案,我忘了张贴在这里。

@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();
    }
}

此解决方案的要点是:
1.使用PowerMockRunner运行我的测试用例:@RunWith(PowerMockRunner.class)
1.指示Powermock为私有字段的操作准备Test.class@PrepareForTest({ Test.class })
1.最后模拟Person类的构造函数:
x1米3英寸x1米4英寸

6l7fqoea

6l7fqoea5#

以下代码可用于初始化REST客户端模拟中的Map器。mapper字段是私有的,需要在单元测试设置期间设置。

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
yeotifhr

yeotifhr6#

如果您正在使用 Spring Boot 测试,并且找不到WhiteBoxFeildSetter;您可以简单地使用org.springframework.test.util.ReflectionTestUtils
这是一个例子:

import org.springframework.test.util.ReflectionTestUtils;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    ReflectionTestUtils.setField(underTestObject, "person", mockedPerson);
    // ...
}
hfwmuf9z

hfwmuf9z7#

如果您需要为所有测试设置相同的变量值,则可以使用@Jarda的指南定义此变量:

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

但是要注意,设置不同的私有值应该小心处理。如果它们是私有的,那是出于某种原因。
例如,我用它来改变单元测试中睡眠的等待时间,在真实的例子中我想睡眠10秒,但是在单元测试中,如果它是即时的,我就满意了,在集成测试中,你应该测试真实的值。

mkh04yzy

mkh04yzy8#

到目前为止,我认为最好的方法是
org.springframework.test.util.ReflectionTestUtils
我将在www.example.com内的FooService.class中模拟private String mockFieldFooServiceTest.java
FooService.java:

@Value("${url.image.latest}")
  private String latestImageUrl;

FooServiceTest.java:

@InjectMocks
  FooService service;

  @BeforeEach
  void setUp() {
    ReflectionTestUtils.setField(service, // inject into this object
        "latestImageUrl", // assign to this field
        "your value here"); // object to be injected
  }
vsdwdz23

vsdwdz239#

通用语言3

import org.apache.commons.lang3.reflect.FieldUtils;

FieldUtils.writeField(object, fieldName, value, true);

相关问题