Spring单元测试中填充@Value注解属性

Spring单元测试中填充@Value注解属性

技术背景

在Spring项目开发中,经常会使用@Value注解从配置文件中注入属性值。在编写单元测试时,有时不希望依赖配置文件,因为配置文件中的值变化可能影响测试结果,而测试的重点是验证代码逻辑,并非属性值本身。因此,需要一种在单元测试中填充@Value注解属性的方法。

实现步骤

方法一:使用ReflectionTestUtils

不使用Spring上下文,在测试中直接创建类的实例,利用ReflectionTestUtilssetField方法设置私有字段。

import org.springframework.test.util.ReflectionTestUtils;

// 被测试的类
@Component
public class MyBean {
    @Value("${this.property.value}")
    private String thisProperty;

    public String getThisProperty() {
        return thisProperty;
    }
}

// 测试类
public class MyBeanTest {
    @Test
    public void testMyBean() {
        MyBean myBean = new MyBean();
        ReflectionTestUtils.setField(myBean, "thisProperty", "testValue");
        assertEquals("testValue", myBean.getThisProperty());
    }
}

方法二:使用@TestPropertySource注解

从Spring 4.1开始,可以在单元测试类上使用@TestPropertySource注解设置属性值。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = FooTest.Config.class)
@TestPropertySource(properties = {
    "some.bar.value=testValue"
})
public class FooTest {

    @Value("${some.bar.value}")
    String bar;

    @Test
    public void testValueSetup() {
        assertEquals("testValue", bar);
    }

    @Configuration
    static class Config {
        @Bean
        public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
            return new PropertySourcesPlaceholderConfigurer();
        }
    }
}

方法三:通过构造函数注入

@Value注解的属性作为构造函数的参数,使类可以在不依赖Spring的情况下进行单元测试。

// 被测试的类
@Component
public class Foo {
    private String property;

    public Foo(@Value("${property.value}") String property) {
        this.property = property;
    }

    public String getProperty() {
        return property;
    }
}

// 单元测试类
public class FooTest {
    @Test
    public void testFoo() {
        Foo foo = new Foo("dummyValue");
        assertEquals("dummyValue", foo.getProperty());
    }
}

// 集成测试类
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;

@SpringBootTest(properties = "property.value=dummyValue")
@RunWith(SpringJUnit4ClassRunner.class)
public class FooIntegrationTest {
    @Autowired
    Foo foo;

    @Test
    public void testFooIntegration() {
        assertEquals("dummyValue", foo.getProperty());
    }
}

核心代码

以下是使用ReflectionTestUtils的核心代码示例:

import org.springframework.test.util.ReflectionTestUtils;

// 被测试的类
public class MyClass {
    @Value("${my.property}")
    private String myProperty;

    public String getMyProperty() {
        return myProperty;
    }
}

// 测试类
public class MyClassTest {
    @Test
    public void testMyClass() {
        MyClass myClass = new MyClass();
        ReflectionTestUtils.setField(myClass, "myProperty", "testValue");
        assertEquals("testValue", myClass.getMyProperty());
    }
}

最佳实践

  • 优先考虑构造函数注入:将@Value注解的属性作为构造函数的参数,使类更易于测试,同时提高代码的可维护性。
  • 避免滥用反射:反射虽然可以解决问题,但会带来运行时错误的风险,且会降低代码的可读性和可维护性。
  • 使用@TestPropertySource:在需要使用Spring上下文的测试中,使用@TestPropertySource注解设置属性值,避免依赖外部配置文件。

常见问题

  • 反射在Java 17及以上版本可能出错:由于Java 17及以上版本对反射的限制更严格,使用ReflectionTestUtils可能会出现错误。可以考虑其他方法,如构造函数注入。
  • @Value注解无法解析占位符:在测试中可能会出现@Value注解无法解析占位符的问题,需要确保Spring上下文中有PropertySourcesPlaceholderConfigurer实例。
### 使用 `@Value` 注解从 YML 文件中读取并显示中文值 在 Spring Boot 应用程序中,通过 `@Value` 注解可以从配置文件(如 application.yml 或 application.properties)中加载属性值。为了确保能够正确处理和显示中文字符,需要注意几个方面。 #### 配置文件编码设置 确保项目的资源文件采用 UTF-8 编码保存,这可以通过 IDE 设置来实现。对于 Maven 项目,可以在 pom.xml 中指定编译器插件的源文件编码为 UTF-8: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> ``` #### YAML 文件中的配置项定义 application.yml 文件内可以这样写入含有中文的内容: ```yaml app: name: "我的应用程序" description: | 这是一个测试应用, 它用于展示如何使用 @Value 注解读取配置。 ``` #### Java 类中使用 `@Value` 注解读取配置 下面给出一个简单的例子说明怎样利用 `@Value` 来访问这些配置数据: ```java import org.springframework.beans.factory.annotation.Value; import lombok.Getter; import lombok.Setter; @Getter @Setter public class AppConfig { @Value("${app.name}") private String appName; @Value("${app.description}") private String appDescription; } ``` 当创建该类的对象实例时,Spring 将自动填充相应的字段值[^1]。 另外,如果遇到像 `${paas.appId}` 获取到的是 `Infinity` 的情况,则可能是由于以下几个原因造成的: - 属性名拼写错误; - properties/yml 文件路径不对或未被识别; - 存在一个默认值覆盖了预期的实际值; 因此建议仔细检查以上几点以排除可能存在的问题[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1010n111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值