有一个java类,它基于Singleton模式。如何为这门课进行单元测试?以下是我的相关代码:
public class ConfigFromFile implements ConfigStrategy {
private String endpoint;
private final static String CONFIG_FILE = "/conf/config.properties";
private InputStream getInputStream(String configFilePath) throws FileNotFoundException{
return new FileInputStream(configFilePath);
}
private void initFromFile() {
Properties prop = new Properties();
InputStream input = null;
try {
input = getInputStream(CONFIG_FILE);
prop.load(input);
endpoint = prop.getProperty("endpoint");
} catch(Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
}
}
private ConfigFromFile() {
initFromFile();
}
private static class ConfigFromFileHolder {
private static ConfigFromFile instance = new ConfigFromFile();
}
public static ConfigFromFile getInstance() {
return ConfigFromFileHolder.instance;
}
@Override
public String getEndpoint() {
return endpoint;
}
}
我需要为这门课写单元测试。
以下是我的情况:
如何实施这些案例?谢谢!
答案 0 :(得分:0)
您可以添加一个包范围构造函数,该构造函数接收要加载的文件的路径,并让您的测试在临时文件夹中创建一个假文件,然后创建一个测试实例,传递到文件的路径。没有必要嘲笑。
public class ConfigFromFile implements ConfigStrategy {
private static final String CONFIG_FILE = "/conf/config.properties";
private final String configFilePath;
private String endpoint;
// Visible for testing
ConfigStrategy(String configFilePath) {
this.configFilePath = configFilePath;
}
private ConfigStrategy() {
this(CONFIG_FILE);
}
private void initFromFile() {
try (InputStream input = new FileInputStream(configFilePath)) {
Properties prop = new Properties();
prop.load(input);
endpoint = prop.getProperty("endpoint");
} catch(Exception e) {
e.printStackTrace();
}
}
...
}
注意我已将initFromFile()
重写为使用try-with-resources ,如果您使用的是JDK 7或更高版本,则可以执行此操作。
您可能想重新考虑此类是否需要是静态单例。它不仅使代码难以测试,而且还可以配置为在不同环境中使用不同的文件。请记住,类的测试是该类的第一个API用户。如果您的测试难以编写,则表明您的API存在问题。
如果您需要限制为一个实例,我建议使用依赖注入框架,如Guice或Spring。如果你使用Spring,你的类可以实现InitializingBean
并在构造类之后但在将它注入另一个类之前加载配置文件:
public class ConfigFromFile implements ConfigStrategy, InitializingBean {
private final String configFilePath;
private String endpoint;
ConfigStrategy(String configFilePath) {
this.configFilePath = configFilePath;
}
@Override
public void afterPropertiesSet() throws IOException {
try (InputStream input = new FileInputStream(configFilePath)) {
Properties prop = new Properties();
prop.load(input);
endpoint = prop.getProperty("endpoint");
}
}
@Override
public String getEndpoint() {
return endpoint;
}
}
是的,这就是您需要的所有代码。
getEndpoint()
检查初始化是否失败你可以和Guice一起做something similar。
但是等等,如果你使用Spring,并且你愿意将端点值移动到Spring配置中,那么它会变得更简单!
public class ConfigFromSpring implements ConfigStrategy {
private final String endpoint;
ConfigStrategy(String endpoint) {
this.endpoint = endpoint;
}
@Override
public String getEndpoint() {
return endpoint;
}
}
课程非常简单,不需要任何单元测试。
您的bean XML看起来像这样:
<bean id="config" class="examples.ConfigFromSpring">
<constructor-arg type="String" value="end of the road"/>
</bean>
当然,此时我将摆脱ConfigStrategy
并在使用配置的对象上设置配置。