2013-01-06 89 views
2

我是初學者,並且保持在手中。 我需要測試這種方法 - 寫入/讀取/從文件。你能得到建議嗎?我能做得更好,只使用junit測試還是更好的EasyMock?你可以建議做什麼?如何使用EasyMock對文件進行測試寫入/讀取

public class AbsFigure { 

public void write(String fileName, List<FigureGeneral> figuresList) { 
    try { 
     PrintWriter out = new PrintWriter(
       new File(fileName).getAbsoluteFile()); 
     try { 
      for (int i = 0; i < figuresList.size(); i++) { 
       out.println(figuresList.get(i).toString()); 
      } 
     } finally { 
      out.close(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Cannot write to file!"); 
    } 
} 

// read from file 
private ArrayList<FigureGeneral> figureReader(String fileName) { 
    String line = null; 
    ArrayList<FigureGeneral> myListFigure = new ArrayList<FigureGeneral>(); 

    try { 
     File myFile = new File(fileName); 
     FileReader fileReader = new FileReader(myFile); 
     BufferedReader bufferedReader = new BufferedReader(fileReader); 

     while ((line = bufferedReader.readLine()) != null) { 
      myListFigure.add(fromStringToFigureGeneral(line)); 
     } 
     System.out.println(myListFigure); 
     bufferedReader.close(); 

    } catch (FileNotFoundException e) { 
     System.out.println("File which You loking for not found!"); 
    } catch (NumberFormatException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     System.out.println("Wrong input!"); 
    } 

    return myListFigure; 
} 

// change from String to FigureGeneral(Triangle or Rectangle) 
private FigureGeneral fromStringToFigureGeneral(String line) { 
    String[] arrayLines = line.split(" "); 
    FigureGeneral figures = null; 

    if (arrayLines[0].equals("triangle")) { 
     figures = new Triangle(Double.parseDouble(arrayLines[1]), 
       Double.parseDouble(arrayLines[2]), "triangle"); 
    } else { 
     figures = new Rectangle(Double.parseDouble(arrayLines[1]), 
       Double.parseDouble(arrayLines[2]), "rectangle"); 
    } 

    return figures; 
} 

public void launch(AbsFigure absFigure) { 
    List<FigureGeneral> figuresList = absFigure.generateRandomFigures(5); 

    AreaCompare areaCompare = new AreaCompare(); 
    Collections.sort(figuresList, areaCompare); 

    absFigure.write("test.txt", figuresList); 
    figureReader("test.txt"); 
} 

public static void main(String[] args) { 
    AbsFigure absFigure = new AbsFigure(); 
    absFigure.launch(absFigure); 
} 
} 

我寫了更多的代碼,並且可以更好地減少情況。我希望你可以推薦如何測試這個(也許你可以展示兩種變體)。

+1

而是嘲諷的類,它是遠遠易於使用的臨時文件。 –

+0

我會讓'figureReader'返回一個'List',我會一直打印出這個異常,除非你添加,而不是放棄信息。 ;)我會將任何附加信息寫入'System.err',因爲你是默認情況下寫入Exceptions的地方。 –

回答

3

通過使用內存I/O,您完全可以避免使用磁盤I/O。您不需要EasyMock,只需輸入和輸出不同的流。您可以通過檢查生成的輸出流(寫入)和圖一般對象的結果列表(讀取)來斷言您的方法正在使用JUnit正常工作。

一步一步:

1)注入,寫入方法將使用輸出流。

您可以添加由您現有的「寫」的方法,另一個叫「寫」的方法,它的輸出流,像這樣的簽名:

public void write(OutputStream outputStream, List<FigureGeneral> figuresList); 

你原來寫的方法將包裝上面的方法通過調用這樣的方法:

write(new FileOutputStream(new File(fileName).getAbsoluteFile()), figuresList); 

2)使用InputStream對讀取方法重複上述技巧。

這將使你有這樣的簽名讀取方法:

private ArrayList<FigureGeneral> figureReader(InputStream inputStream); 

3)現在編寫使用ByteArrayInputStream的和ByteArrayOutputStream,並調用上面的方法JUnit測試。

您可以通過在ByteArrayOutputStream上調用toByteArray()並聲明結果來檢查寫入方法的結果。您可以通過在傳遞給定的ByteArrayInputStream之後聲明List中的值來檢查讀取方法的結果。

下面是一個(僞)方法,您可以添加到您的測試類來聲明不同性質的FigureGeneral對象列表可以寫入輸出流,從輸入流回讀並相等。

public void assertCanBeWrittenAndReaback(List<FigureGeneral> inputFigure) { 
    ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
    absFigure.write(outStream, inputFigures); 
    List<FigureGeneral> outputFigure = absFigure.figureReader(new ByteArrayInputStream(outStream.toByteArray())); 
    assertEqualsFigureGeneralLists(inputFigure, outputFigure); 
} 

4)這會給你一個很好的測試覆蓋率。儘管如此,如果你想達到100%的測試覆蓋率,你仍然必須測試現在已經成爲包裝的原始寫和讀圖方法。

原始方法只不過是重定向到使用輸入和輸出流的同名文件。你可以通過覆蓋(或者如果你把這些方法放在一個接口後面)這兩個重定向方法並聲明它們接收到合適的FileInputStream和FileOutputStream對象,來使用EasyMock檢查它們的重定向。您將需要一些臨時文件,因爲FileOutputStream構造函數需要一個現有的文件。但是,在測試用例中使用臨時文件時看不到任何主要問題。

+1

你能更好地展示一下如何使用原創的寫入方法來包裝另一個寫入方法... –

1

經驗法則是:只模擬你擁有的東西。嘲笑文件讀者和作者並不是一個好主意。在這種情況下集成測試更好 - 您想要測試您是否正確地將代碼與Java IO API集成在一起。因此,只需將數據寫入某個臨時文件並再次讀取即可。

如果您將在更多地方使用IO API,您應該考慮通過IO API創建自定義包裝並使用集成測試對其進行測試。然後你只能使用包裝來訪問文件系統,你可以輕鬆地嘲笑它。這樣你就不必爲每個訪問文件系統的類編寫集成測試。你只是測試它與你的包裝正確交互(使用mocks)。

1

建立一個臨時測試文件然後檢查它的內容可能會更好,類似於this SO question

1

我建議你,這是在此情況下,更好的覆蓋範圍之一:

你讓臨時方法setUp()在註釋@Before.

和初始化所有你在這個方法中所需要的。

您在拆除方法 - releaseResources()註釋@After,您刪除您的temoorary文件。

而且使@Test所有oppotunity情況下,如果測試失敗,拋出new RuntimeException():

public class AbsFigureTest { 

    public static final String defaultTestPath = "unittest.tmp"; 
    private List<FigureGeneral> inputFigures; 
    private List<FigureGeneral> outputFigures; 
    private DeepCompare deepCompare; 

    @Before 
    public void setUp() throws FigureGeneralFilesFoundException, 
      FigureGeneralFormatException { 
     inputFigures = absFigure.generateRandomFigures(5); 
     absFigure.write(defaultTestPath, inputFigures); 
     outputFigures = absFigure.figureReader(defaultTestPath); 
     deepCompare = new DeepCompare(); 
} 

    @After 
    public void releaseResources() { 
     new File(defaultTestPath).delete(); 
    } 

    @Test 
    public void assertEquals_FigureGeneralLists_ReturnZero() { 
     for (int i = 0; i < inputFigures.size(); i++) { 
      FigureGeneral inputValue = inputFigures.get(i); 
      FigureGeneral outputValue = outputFigures.get(i); 

      if (deepCompare.compare(inputValue, outputValue) != 0) 
       throw new RuntimeException("not equal"); 
     } 

    } 

    @Test 
    public void testDeepCompRectangle_EqualResult_ReturnZero() { 
     FigureGeneral oneFigure = new Rectangle(2.0, 2.0, "rectangle"); 
     FigureGeneral twoFigure = new Rectangle(2.0, 2.0, "rectangle"); 
     int result = deepCompare.compare(oneFigure, twoFigure); 
     assertTrue("expected to be equal", result == 0); 
    } 

    @Test 
    public void testDeepCompTriangle_EqualResult_ReturnZero() { 
     FigureGeneral oneFigure = new Triangle(2.0, 2.0, "rectangle"); 
     FigureGeneral twoFigure = new Triangle(2.0, 2.0, "rectangle"); 
     int result = deepCompare.compare(oneFigure, twoFigure); 
     assertTrue("expected to be equal", result == 0); 
    } 

    @Test 
    public void testDeepComp_GreaterThan_ReturnOne() { 
     FigureGeneral oneFigure = new Triangle(2.0, 2.0, "triangle"); 
     FigureGeneral twoFigure = new Rectangle(1.0, 1.0, "rectangle"); 
     int result = deepCompare.compare(oneFigure, twoFigure); 
     assertTrue("expected to be greater than", result >= 1); 

     if (deepCompare.compare(oneFigure, twoFigure) != 0) 
      throw new RuntimeException("not equal"); 
    } 
} 
+1

這是一個真正的好覆蓋面。謝謝! –

相關問題