vendredi 6 décembre 2019

I can not test singleton without load() method

When I start the application, I need to load properties from different sources: war, file system, database, and JVM. I need to load properties once and use them within running my application. I do not need to refresh it. I don't have DI - it is a simple java application with singletons. I decide to create AppProperties singleton and load properties when starting the application. It is the best solution by the current time for me(I hope somebody makes the best solution). It is my Singleton:

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;
    }
}

But I do not understand, How can I use it in tests. Because I hardcode paths for aplication.properties files. And when I will create this instance in the tests, I will create AppProperties with real properties.

I tried to add a public method like load(filePath). But with this method, it will be not a singleton. If somebody will call this method in another place of application - my singleton will be reloaded with new data. Now I have 2 problems.

  1. If I add load() method - it will be dangerous for reloading data. But I can use it in tests.
  2. If I do not add this method - I can not test it.

P.S I read this article The Little Singleton

But I do not understand some moments. If I have singleton with private constructor, I can not extend it like in article.

Aucun commentaire:

Enregistrer un commentaire