Writing to a File


You will now need to update RosterReporter to be able to take a filename as a parameter. The test will need to make sure that the report is properly written to an operating system file.

First, you will refactor RosterReporterTest to create a setUp method and an assertion method assertReportContents. By doing so, you will set the stage to quickly add a new test, testFiledReport, that uses these common methods and thus introduces no duplication.

Within assertReportContents, you can modify the assertion to obtain the number of expected students from the session object. You will need to change getNumberOfStudents in Session from package to public.

The refactored RosterReporterTest:

 package sis.report; import junit.framework.TestCase; import sis.studentinfo.*; import java.io.*; public class RosterReporterTest extends TestCase {    private Session session;    protected void setUp() {       session =          CourseSession.create(             new Course("ENGL", "101"),             DateUtil.createDate(2003, 1, 6));       session.enroll(new Student("A"));       session.enroll(new Student("B"));    }    public void testRosterReport() throws IOException {       Writer writer = new StringWriter();       new RosterReporter(session).writeReport(writer); assertReportContents(writer.toString());    }    private void assertReportContents(String rosterReport) {       assertEquals(          String.format(RosterReporter.ROSTER_REPORT_HEADER +                        "A%n" +                        "B%n" +                        RosterReporter.ROSTER_REPORT_FOOTER,                        session.getNumberOfStudents()),          rosterReport);    } } 

The new test, testFiledReport, calls an overloaded version of writeReport. This second version of writeReport takes a filename instead of a Writer as a parameter.

 public void testFiledReport() throws IOException {    final String filename = "testFiledReport.txt";    new RosterReporter(session).writeReport(filename);    StringBuffer buffer = new StringBuffer();    String line;    BufferedReader reader =       new BufferedReader(new FileReader(filename));    while ((line = reader.readLine()) != null)       buffer.append(String.format(line + "%n"));    reader.close();    assertReportContents(buffer.toString()); } 

After calling writeReport, the test uses a BufferedReader to read the contents of the report file into a buffer. The test then passes the buffer's contents to the assertReportContents method.

A BufferedReader is a Reader subclass that can wrap another reader. Remember that you use Reader objects to read from character streams. The test constructs a BufferedReader with a FileReader as a parameter. A FileReader is a character-based input stream that can read data from a file. You construct a FileReader using a filename.

You could read the file's contents by directly using a FileReader instead of a BufferedReader. However, a BufferedReader is more efficient since it buffers characters as it reads. In addition, BufferedReader supplies the method readLine to help you simplify your code. The readLine method returns a logical line of input from the wrapped stream, using the system property "line.separator" to delineate lines.

The new method in RosterReporter:

 void writeReport(String filename) throws IOException {    Writer bufferedWriter =       new BufferedWriter(new FileWriter(filename));    try {       writeReport(bufferedWriter);    }    finally {       bufferedWriter.close();    } } 

The writeReport method creates a FileWriter using the filename passed to it. It wraps the FileWriter in a BufferedWriter. The method then passes the writer to the existing writeReport method (which takes a PrintWriter as a parameter).

A finally block ensures that the PrintWriter is always closed, regardless of whether writeReport threw an exception or not. You must remember to close file resources, otherwise you may encounter locked file problems. Also, buffered information will not appear in the file until you close the Writer. You can also use the Writer method flush to force the Writer to write its contents to the destination.

Notice that you were able to add functionality to the existing Roster-Reporter class without modifying a single line of its code. You simply added a new method. Achieving this ideal happens more often if you strive to ensure that your code maintains an optimal design at all times. Prefer the use of abstractions in your code.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net