JAVASpring

Spring的ReflectionTestUtils

简介


ReflectionUtils是Spring中一个常用的类,属于spring-core包;ReflectionTestUtils则属于spring-test包。两者功能有重叠的地方,而ReflectionUtils会更强大。在单元测试时使用ReflectionTestUtils,能增加我们的便利性。

假设我们需要创建一个类,但它的某些成员变量是私有的,并且没有提供公共的setter方法,而我们无法按照它的正常初始化流程来使它的这些成员变量是我们想要的值。这时就需要想办法修改一个类的私有变量,而反射可以帮助到我们。Spring也提供了反射相关的工具类:ReflectionUtils和ReflectionTestUtils,这里只介绍ReflectionTestUtils的常用功能。

ReflectionTestUtils主要方法


获取对象的成员变量:

public static Object getField(@Nullable Object targetObject, String name)

给对象注入成员变量:

public static void setField(Class<?> targetClass, String name, @Nullable Object value)

调用成员方法:

public static <T> T invokeMethod(Object target, String name, Object... args)

使用例子:


当使用junit来测试Spring的代码时,为了减少依赖,需要给对象的依赖,设置一个mock对象,但是由于Spring可以使用@Autoware类似的注解方式,对私有的成员进行赋值,此时无法直接对私有的依赖设置mock对象。可以通过引入ReflectionTestUtils,解决依赖注入的问题。

在Spring框架中,可以使用注解的方式如:@Autowair、@Inject、@Resource,对私有的方法或属性进行注解赋值,如果需要修改赋值,可以使用ReflectionTestUtils达到目的。

待测试类:Foo

package com.github.yongzhizhan.draftbox.springtest;
 
import org.springframework.beans.factory.annotation.Autowired;
 
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
 
/**
 * 被测类
 */
@Service
public class Foo {
    @Autowired
    private String m_String;
 
    @PostConstruct
    private void onStarted(){
        System.out.println("on started " + m_String);
    }
 
    @PreDestroy
    private void onStop(){
        System.out.println("on stop " + m_String);
    }
}

使用ReflectionTestUtils解决依赖注入

package com.github.yongzhizhan.draftbox.springtest;
 
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
 
/**
 * 使用ReflectionTestUtils解决依赖注入
 * @author 
 */
public class ReflectionTestUtilsTest {

    @Autowired
    private Foo tFoo;

    @Test
    public void testDefault(){
 
        //set private property
        ReflectionTestUtils.setField(tFoo, "m_String", "Hello");
 
        //invoke construct and destroy method
        ReflectionTestUtils.invokeMethod(tFoo, "onStarted");
        ReflectionTestUtils.invokeMethod(tFoo, "onStop");
    }
}