Java 通过在重构之前重写私有类变量作为初始步骤来测试方法

Java 通过在重构之前重写私有类变量作为初始步骤来测试方法,java,unit-testing,legacy-code,Java,Unit Testing,Legacy Code,为使用private配置变量(config)的方法编写单元测试的最佳方式是什么,例如mysetProperties(见下文)。我尝试使用反射和Makito来覆盖它,但失败了,但没有成功。我意识到改变设计使代码更易于测试是最好的,但我想在重构代码之前创建一些单元测试 public class MainClass { private final java.lang.String config = "app.properties"; public TestClass() {

为使用
private
配置变量(
config
)的方法编写单元测试的最佳方式是什么,例如my
setProperties
(见下文)。我尝试使用反射和Makito来覆盖它,但失败了,但没有成功。我意识到改变设计使代码更易于测试是最好的,但我想在重构代码之前创建一些单元测试

public class MainClass {
    private final java.lang.String config = "app.properties";

    public TestClass() {
        try {
            setProperties();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setProperties() throws Exception {
        try {
            InputStream input = new BufferedInputStream(new FileInputStream(config));
            ..
            ..
        } catch (Exception exception) {
            throw exception;
        }
    }
}

这表明设计有缺陷;不要硬编码这样的东西。更好的是,确定该类的适当责任是什么,并按优先顺序递减:

  • 传入具有强类型配置属性的对象
  • 传入带有配置属性的
    映射
  • 为属性文件传入一个
    InputStream

由于jar中永远无法使用
File
对象,所以您不应该让这样的接口比
InputStream
Reader
更具体,这样您就可以始终从jar类路径传入流。

所以您可以使用Java中的Properties类来实现这一点。请看一下这个代码

public class PropertyUtil {

        private static Properties prop;

        private static Logger logger = Logger.getLogger(PropertyUtil.class);

        private PropertyUtil() {

        }

        public void setProperty() {
            String filePath = System.getenv("JAVA_HOME") + "/lib" + "/my_file.properties";
            prop = new Properties();

            try (InputStream input = new FileInputStream(filePath)) {
                prop.load(input);
            } catch (IOException ex) {
                logger.error("Error while reading property file " + ex);
            }
        }

        public static String getProperty(String key) {
            if (prop.containsKey(key)) {
                return prop.getProperty(key);
            } else {
                return null;
            }
        }

        public static <T> T getProperty(String key, Class<T> claz) {

            if (claz.getName().equals(Integer.class.getName())) {
                return claz.cast(Integer.parseInt(prop.getProperty(key)));
            }
            if (claz.getName().equals(Long.class.getName())) {
                return claz.cast(Long.parseLong(prop.getProperty(key)));
            }
            if (claz.getName().equals(Boolean.class.getName())) {
                return claz.cast(Boolean.parseBoolean(prop.getProperty(key)));
            }
            if (claz.getName().equals(Double.class.getName())) {
                return claz.cast(Double.parseDouble(prop.getProperty(key)));
            }
            if (claz.getName().equals(String.class.getName())) {
                return claz.cast(prop.getProperty(key));
            }

            return null;
        }
公共类属性直到{
私有静态属性;
私有静态记录器=Logger.getLogger(PropertyUtil.class);
私有财产直到(){
}
public void setProperty(){
字符串filePath=System.getenv(“JAVA_HOME”)+“/lib”+“/my_file.properties”;
prop=新属性();
try(InputStream输入=新文件InputStream(文件路径)){
道具载荷(输入);
}捕获(IOEX异常){
logger.error(“读取属性文件时出错”+ex);
}
}
公共静态字符串getProperty(字符串键){
if(附件containsKey(图例)){
返回prop.getProperty(键);
}否则{
返回null;
}
}
公共静态getProperty(字符串键,类claz){
if(claz.getName().equals(Integer.class.getName())){
返回claz.cast(Integer.parseInt(prop.getProperty(key));
}
if(claz.getName().equals(Long.class.getName())){
return claz.cast(Long.parseLong(prop.getProperty(key));
}
if(claz.getName().equals(Boolean.class.getName())){
返回claz.cast(Boolean.parseBoolean(prop.getProperty(key));
}
if(claz.getName().equals(Double.class.getName())){
return claz.cast(Double.parseDouble(prop.getProperty(key));
}
if(claz.getName().equals(String.class.getName())){
返回claz.cast(prop.getProperty(key));
}
返回null;
}

通过提取一个带有参数的方法来重构一点,该参数接受一个输入流。调用这个新方法(可能受包保护)从旧方法开始。针对新方法编写测试。然后进行更多重构。

发布
setProperties
方法的完整代码,或者只模拟配置文件的问题?问题是模拟或重写私有变量。我想要一种在单元测试期间更改该私有变量值的方法。请删除
java.lang.
before
String
@luk2302为什么?在限定String时有风险吗?“我不能使用反射”-您实际尝试了什么?您看到了吗?我知道这个问题,我正在寻找重构前的单元测试解决方案。不幸的是,这段代码不是我自己的,无法更改。