Java 如果没有load()方法,我无法测试singleton
启动应用程序时,我需要从不同的源加载属性:war、文件系统、数据库和JVM。我需要加载一次属性,并在运行应用程序时使用它们。我不需要刷新它。我没有DI——它是一个简单的java应用程序,带有单例。我决定在启动应用程序时创建AppProperties单例并加载属性。这是目前对我来说最好的解决方案(我希望有人能做出最好的解决方案)。这是我的单身汉:Java 如果没有load()方法,我无法测试singleton,java,unit-testing,testing,design-patterns,singleton,Java,Unit Testing,Testing,Design Patterns,Singleton,启动应用程序时,我需要从不同的源加载属性:war、文件系统、数据库和JVM。我需要加载一次属性,并在运行应用程序时使用它们。我不需要刷新它。我没有DI——它是一个简单的java应用程序,带有单例。我决定在启动应用程序时创建AppProperties单例并加载属性。这是目前对我来说最好的解决方案(我希望有人能做出最好的解决方案)。这是我的单身汉: import java.io.InputStream; import java.util.Properties; public class AppPr
import java.io.InputStream;
import java.util.Properties;
public class AppProperties {
private static AppProperties instance;
private Properties propertiesFromWar;
private Properties propertiesFromFile;
private Properties propertiesFromDB;
private AppProperties() {
propertiesFromWar = new Properties();
try {
propertiesFromWar.load(getPropertiesAsInputStreamFromWar());
propertiesFromFile.load(getPropertiesAsInputStreamFromFile());
propertiesFromDB.load(getPropertiesAsInputStreamFromDB());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private InputStream getPropertiesAsInputStreamFromDB() {
//some implementation
return null;
}
private InputStream getPropertiesAsInputStreamFromFile() {
//some implementation
return null;
}
private InputStream getPropertiesAsInputStreamFromWar() {
return getClass().getResourceAsStream("META-INF/application.properties");
}
public static AppProperties getInstance() {
if (instance == null) {
instance = new AppProperties();
}
return instance;
}
public String getProperty(String key) {
String value;
value = System.getProperty(key);
if (value == null) {
value = propertiesFromDB.getProperty(key);
if (value == null) {
value = propertiesFromFile.getProperty(key);
if (value == null) {
value = propertiesFromWar.getProperty(key);
}
}
}
return value;
}
}
但我不明白,我如何在测试中使用它。因为我硬编码了aplication.properties文件的路径。当我在测试中创建这个实例时,我将使用真实属性创建AppProperties
我尝试添加一个公共方法,如load(filePath)
。但有了这个方法,它将不再是一个单例。如果有人在另一个应用程序中调用此方法,我的单例将重新加载新数据。现在我有两个问题
但有些时候我不明白。如果我有带私有构造函数的singleton,我不能像本文中那样扩展它。因为测试允许指定JVM启动参数,所以这可以很容易地“解决”。
这也增加了一些灵活性
java -DpropertiesPath="..." -jar yourJar.jar
并且,修改您的代码
private InputStream getPropertiesAsInputStreamFromWar(){
最后一个字符串propertiesPath=Objects.requirennull(System.getProperty(“propertiesPath”);
返回getClass().getResourceAsStream(propertiesPath);
}
您可以使用默认值,例如META-INF/application.properties
在测试资源目录中,创建META-INF
目录。这里创建一个文件application.properties
,并在其中添加一些用于测试的属性
运行测试时,请确保上面的目录位于类路径中。这样,当调用
getPropertiesAsInputStreamFromWar()
时,它将在类路径中查找META-INF/application.properties
如果我是你,我就不会在这里用单身汉。这是一种被过度使用的模式,类似于SomeClass.getInstance()
的代码使得测试比应该的要困难得多。如果代码很难进行单元测试,可能应该对其进行重构。将Singelton
用作概念,而不是语言模板。