Java 什么';测试类静态初始值设定项的最佳方法是什么?
我有一个类,它有相当复杂的静态初始化。我从一个目录中读取文件,然后解析这些json文件,映射到对象,并填写一个列表。您可以想象,可能会出现一些异常,我需要介绍并测试这些代码分支。问题是这个静态初始化只运行一次/Testcase文件。 我跨越的解决方案:Java 什么';测试类静态初始值设定项的最佳方法是什么?,java,junit,static-initializer,Java,Junit,Static Initializer,我有一个类,它有相当复杂的静态初始化。我从一个目录中读取文件,然后解析这些json文件,映射到对象,并填写一个列表。您可以想象,可能会出现一些异常,我需要介绍并测试这些代码分支。问题是这个静态初始化只运行一次/Testcase文件。 我跨越的解决方案: 每个行为的新测试用例文件 卸载静态类 新JVM 我对这些选项不感兴趣,难道没有更好的方法吗?如果您无法避免静态初始值设定项,请将其提取到方法体。然后是测试方法。静态初始值设定项看起来像是static{myMethod();},几乎不能被破坏。
- 每个行为的新测试用例文件
- 卸载静态类
- 新JVM
我对这些选项不感兴趣,难道没有更好的方法吗?如果您无法避免静态初始值设定项,请将其提取到方法体。然后是测试方法。静态初始值设定项看起来像是
static{myMethod();}
,几乎不能被破坏。单元测试中的一个重要因素是对代码进行结构化,使其适合测试
不幸的是,正如您所发现的,执行复杂IO操作的静态初始化过多的代码不是一个容易测试的结构
除了静态初始化之外,听起来您的代码违反了in,就像一个类从外部源加载自己一样,可能还有其他用途
因此,您需要进行一些重构,例如,如果您的代码看起来像这样(为了清晰起见,JSON解析替换为CSV解析):
如果看不到您的代码或不知道文件格式,很难对其进行扩展,但希望您能了解要点
最后,静态初始化将是:
public MyClass
{
private static List<MyObject> myObjects = new ArrayList<>();
static
{
loadMyObjects(new FileReader("myfile.csv"));
}
/* package */ static void loadMyObjects(Reader reader)
{
try
{
try (MyObjectReader reader = new new MyObjectReader(reader))
{
MyObject myObject;
while ((myObject = reader.read()) != null)
{
myObjects.add(myObject);
}
}
}
catch (IOException e)
{
...
}
}
}
公共MyClass
{
私有静态列表myObjects=newarraylist();
静止的
{
loadMyObject(新文件阅读器(“myfile.csv”);
}
/*包*/静态无效加载对象(读卡器)
{
尝试
{
try(MyObjectReader=新建MyObjectReader(reader))
{
肌体肌体;
while((myObject=reader.read())!=null)
{
myObjects.add(myObject);
}
}
}
捕获(IOE异常)
{
...
}
}
}
在这里测试快乐之路可能是值得的,但就我个人而言,
loadMyObjects
方法现在非常简单,我可能不会费心了。可能是Wow的复制品,感谢您提供了全面详细的答案。对于IO繁重的任务,单独的reader类是一个好主意。Nick Holt给出了更详细的答案,但基本思想是一样的。谢谢:)
public class MyObjectReader implements Closeable
{
private BufferredReader reader;
public MyObjectReader(Reader reader)
{
this.reader = new BufferredReader(reader);
}
public MyObject read() throws IOException
{
String line = reader.readLine();
if (line != null)
{
String[] tokens = line.split(",");
if (tokens.length < 3)
{
throw new IOException("Invalid line encountered: " + line);
}
return new MyObject(tokens[0], tokens[1], tokens[2]);
}
else
{
return null;
}
}
public void close() throws IOException
{
this.reader.close();
}
}
public MyObjectReaderTest
{
@Test
public void testRead() throws IOException
{
String input = "value1.1,value1.2,value1.3\n" +
"value2.1,value2.2,value2.3\n" +
"value3.1,value3.2,value3.3";
try (MyObjectReader reader = new MyObjectReader(new StringReader(input)))
{
assertEquals(new MyObject("value1.1", "value1.2", "value1.3"), reader.read());
assertEquals(new MyObject("value2.1", "value2.2", "value2.3"), reader.read());
assertEquals(new MyObject("value3.1", "value3.2", "value3.3"), reader.read());
assertNull(reader.read());
}
}
@Test(expected=IOException.class)
public void testReadWithInvalidLine() throws IOException
{
String input = "value1.1,value1.2";
try (MyObjectReader reader = new MyObjectReader(new StringReader(input)))
{
reader.read();
}
}
}
public MyClass
{
private static List<MyObject> myObjects = new ArrayList<>();
static
{
loadMyObjects(new FileReader("myfile.csv"));
}
/* package */ static void loadMyObjects(Reader reader)
{
try
{
try (MyObjectReader reader = new new MyObjectReader(reader))
{
MyObject myObject;
while ((myObject = reader.read()) != null)
{
myObjects.add(myObject);
}
}
}
catch (IOException e)
{
...
}
}
}