2013-01-06 111 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

这是一个真正的好覆盖面。谢谢! –