There is a java class, it is based on Singleton pattern. how to do unit test for this class? the following is my related code:
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;
}
}
I need to write unit test for this class.
The following is my case:
how to implement these cases? Thanks!
You can add a package-scope constructor that takes in the path of the file to load , and have your test create a fake file in a temporary folder, and then create an instance of your test, passing in the path to the file. No mocking necessary.
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();
}
}
...
}
Note I rewrote initFromFile()
to use try-with-resources , which you can do if if you are using JDK 7 or above.
You might want to reconsider whether this class needs to be a static singleton. It not only makes the code harder to test, but it can't be configured to use different files in different environments. Remember that the test for a class is the class's first user of the API . If your test is hard to write, that can indicate problems with your API.
If you need to restrict to one instance, I suggest using a dependency injection framework like Guice or Spring. If you use Spring, your class can implement InitializingBean
and load the configuration file after the class is constructed but before it is injected into another class:
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;
}
}
Yes, that's all the code you need.
getEndpoint()
check if the initialization failed You can do something similar with Guice.
But wait, if you use Spring, and you are willing to move the endpoint value into the Spring configuration, then it gets even simpler!
public class ConfigFromSpring implements ConfigStrategy {
private final String endpoint;
ConfigStrategy(String endpoint) {
this.endpoint = endpoint;
}
@Override
public String getEndpoint() {
return endpoint;
}
}
The class is so simple, it doesn't need any unit tests.
Your bean XML would look like this:
<bean id="config" class="examples.ConfigFromSpring">
<constructor-arg type="String" value="end of the road"/>
</bean>
Of course, at this point I would get rid of ConfigStrategy
and set the configuration on the object that uses the configuration.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.