测试数据初始化最佳实践:非Spring框架下属性文件替代方案咨询
无Spring框架的属性文件优化方案
1. 单例属性读取器+集中式键常量类
不用为每个模块单独创建类,而是用一个全局单例的属性读取工具类,搭配一个集中管理所有属性键的常量类,既避免重复初始化读取器,又能统一维护键值,杜绝硬编码。
示例代码:
- 属性读取工具类(单例实现):
import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertyReader { private static final PropertyReader INSTANCE = new PropertyReader(); private final Properties properties = new Properties(); private PropertyReader() { // 批量加载所有属性文件,可根据需求添加多个 loadProperties("login.properties"); loadProperties("common.properties"); } private void loadProperties(String fileName) { try (InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) { if (is != null) { properties.load(is); } } catch (IOException e) { throw new RuntimeException("加载属性文件失败: " + fileName, e); } } public static PropertyReader getInstance() { return INSTANCE; } public String getProperty(String key) { return properties.getProperty(key); } }
- 属性键常量类:
public class PropertyKeys { // 登录模块相关键 public static final String LOGIN_BUTTON_TEXT = "login-page.login-button.text"; public static final String WRONG_PASSWORD_NOTIFICATION = "login-page.notification.wrong-password"; // 其他模块键可在此扩展 }
- 断言时的调用方式:
Assert.that(actualNotification, PropertyReader.getInstance().getProperty(PropertyKeys.WRONG_PASSWORD_NOTIFICATION));
2. 类型安全的枚举式属性访问器
如果想在编译期就避免传错属性键的问题,可以用枚举封装每个属性的键和读取逻辑,实现类型安全的属性访问,同时省去单独的常量类。
示例代码:
import java.io.IOException; import java.io.InputStream; import java.util.Properties; public enum AppProperties { LOGIN_BUTTON_TEXT("login-page.login-button.text"), WRONG_PASSWORD_NOTIFICATION("login-page.notification.wrong-password"); private final String key; private static Properties properties; static { // 静态块加载所有属性文件 try (InputStream loginIs = AppProperties.class.getClassLoader().getResourceAsStream("login.properties")) { properties = new Properties(); properties.load(loginIs); // 可追加加载其他属性文件 properties.load(AppProperties.class.getClassLoader().getResourceAsStream("common.properties")); } catch (IOException e) { throw new RuntimeException("加载属性文件失败", e); } } AppProperties(String key) { this.key = key; } public String getValue() { return properties.getProperty(key); } }
- 断言时的调用方式:
Assert.that(actualNotification, AppProperties.WRONG_PASSWORD_NOTIFICATION.getValue());
3. 接口式模块化属性分组
如果希望按模块拆分属性键,但又不想每个模块都创建带初始化逻辑的类,可以用接口做模块级的常量容器,搭配统一的单例读取器使用。
示例代码:
// 登录模块属性键接口 public interface LoginPropertyKeys { String LOGIN_BUTTON_TEXT = "login-page.login-button.text"; String WRONG_PASSWORD_NOTIFICATION = "login-page.notification.wrong-password"; } // 订单模块属性键接口(示例) public interface OrderPropertyKeys { String ORDER_CONFIRM_BUTTON_TEXT = "order-page.confirm-button.text"; }
- 断言时的调用方式:
Assert.that(actualNotification, PropertyReader.getInstance().getProperty(LoginPropertyKeys.WRONG_PASSWORD_NOTIFICATION));
这几种方案都比创建多个带public static final字段的类更高效:要么减少冗余代码、集中管理配置,要么提供编译期类型安全,要么兼顾模块化与简洁性,且均为纯Java实现,无需依赖Spring框架。
内容的提问来源于stack exchange,提问作者Keker
相关产品推荐
相关产品推荐

