Важным фактором в модульном тестировании является структурирование вашего кода, чтобы он был подходящим для тестирования.
К сожалению, как вы выяснили, код с чрезмерной статической инициализацией, выполняющей сложные операции ввода-вывода, не является проверенной структурой.
Помимо статической инициализации, это похоже на то, что код нарушает single-responsibility principle так же, как класс загружает себя из внешнего источника и, как правило, имеет какое-то другое применение.
Итак, вы получили некоторые рефакторинга делать, например, если ваш код был выглядеть примерно так (JSON синтаксического анализа, заменен CSV разбора для ясности):
public MyClass
{
private static List<MyObject> myObjects = new ArrayList<>();
static
{
try
{
try (BufferedReader reader = new BufferedReader(new FileReader(myfile.csv))
{
String line;
while ((line = reader.readLine()) != null)
{
String[] tokens = line.split(",");
myObjects.add(new MyObject(tokens[0], tokens[1], tokens[2]));
}
}
}
catch (IndexOutOfBoundsException e)
{
...
}
catch (IOException e)
{
...
}
}
}
Тогда вы могли бы извлечь это основная часть логики в обычай читателя класса, что-то вроде этого:
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();
}
}
MyObjectReader
класса вполне проверяем и, что важно не полагаться на файлы или других ресурсах, присутствуя, так Вы можете проверить это следующим образом:
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)
{
...
}
}
}
Это может быть стоит испытывать счастливый путь здесь, но лично метод loadMyObjects
теперь так просто я, вероятно, не будет беспокоить.
Возможный дубликат [Как заставить статический блок работать в каждом методе тестирования?] (Http://stackoverflow.com/questions/5784277/how-to-force-the-static-block-running-in-each -test-method) – icza