java - 没有 load() 方法我无法测试单例

标签 java unit-testing testing design-patterns singleton

当我启动应用程序时,我需要从不同的来源加载属性:war、文件系统、数据库和 JVM。我需要加载一次属性并在运行我的应用程序时使用它们。我不需要刷新它。我没有 DI——它是一个简单的单例 Java 应用程序。我决定在启动应用程序时创建 AppProperties 单例并加载属性。对我来说这是目前最好的解决方案(我希望有人能做出最好的解决方案)。这是我的单例:

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。

我尝试添加一个公共(public)方法,如 load(filePath)。但是用这个方法,它就不是单例了。如果有人将在另一个应用程序中调用此方法 - 我的单例将重新加载新数据。现在我有 2 个问题。

  1. 如果我添加 load() 方法 - 重新加载数据会很危险。但我可以在测试中使用它。
  2. 如果我不添加这个方法——我无法测试它。

P.S 我看了这篇文章The Little Singleton

但有些时候我不明白。如果我有带有私有(private)构造函数的单例,我不能像文章中那样扩展它。

最佳答案

在您的测试资源目录中,创建META-INF 目录。这里创建一个文件 application.properties 并在其中添加一些用于测试目的的属性。

当您运行测试时,请确保上述目录位于类路径中。这样,当调用 getPropertiesAsInputStreamFromWar() 时,它将在类路径中查找 META-INF/application.properties

关于java - 没有 load() 方法我无法测试单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59210851/

相关文章:

java - java.util.Stack 或 java.util.Queue 有什么线程安全问题

javascript - AngularJS 单元测试 : Injected Services undefined

objective-c - 从 Swift 测试文件调用 Objective-C 类

python - 在 Pytest 断言中覆盖标准断言消息传递

javascript - Testcafe t.typeText 使用 { 粘贴 : true } by default

java - java中如何调用类的静态 block

java - 如何从通用数组列表中找到最小值?

java - 将可变参数传递给方法

python - fileinput.input 的单元测试

node.js - 为什么在使用 jest 测试 Node 应用程序时看不到控制台日志输出