0

i hava this method separateOfficers() that will read from the input text file, record by record (line by line), writing into the appropriate output text file (officers registered in 2021, 2022 and 2023 will be stored in awc21.txt, awc22.txt and awc23.txt,respectively), and also counting the number of officers in each output file.

public static void SeparateOfficers() {

        try {
            readfile = new BufferedReader(new FileReader("awc.txt"));
            String line = readfile.readLine();
            String newline;

            PrintWriter write21 = new PrintWriter(new FileOutputStream("awc21.txt"));
            PrintWriter write22 = new PrintWriter(new FileOutputStream("awc22.txt"));
            PrintWriter write23 = new PrintWriter(new FileOutputStream("awc23.txt"));
            
            int a21=0,a22=0,a23=0;
            while (line != null) {
                newline = line;
                StringTokenizer tokenizer = new StringTokenizer(line);
                String s = (tokenizer.nextToken()).substring(0, 2);

                switch (Integer.parseInt(s)) {
                    case 21 ->{
                         write21.println(newline);
                         a21++;
                    }
                    case 22 ->
                    {
                        write22.println(newline);
                        a22++;
                    }
                    case 23 ->
                    {
                        write23.println(newline);
                        a23++;
                    }
                    default -> {
                        System.out.println("*This UOB numbers is not in the specific range*");
                        System.out.println(newline + "\n");
                    }

                }

                line = readfile.readLine();
            }
            write21.close();
            write22.close();
            write23.close();
        } catch (FileNotFoundException e) {
            System.out.println("File Not Found");
        } catch (IOException e) {
            System.out.println("Error reading from the file");
        }
    }

and i cant make a unit test method foe it. it should Identify a minimal test set, as a set of records in testOfficers.txt for testing this method and insert it, as comment, at the beginning of the testing method. The output files will be testOfficers21.txt, testOfficers22.txt and testOfficers23.txt.

1 Answers1

0

this code is hard to test because it's tightly coupled with these files. Though, we can try to do something using SretingReader and StringWriter.

Firstly, you need to move all the file declarations outside of the class and pass them as parameters to the function:

public static void SeparateOfficers(
               PrintWriter write21, PrintWriter write22, 
               PrintWriter write23, Reader reader) {
   try {
      BufferedReader readfile = new BufferedReader(reader);
      // ...
   }
   // ...
}

Then, your "production" code, will need to open these files and pass these readers and writers, you can do it like this:

public void productionCall() throws Exception {
    PrintWriter write21 = new PrintWriter(new FileOutputStream("awc21.txt"));
    PrintWriter write22 = new PrintWriter(new FileOutputStream("awc22.txt"));
    PrintWriter write23 = new PrintWriter(new FileOutputStream("awc23.txt"));
    FileReader fr = new FileReader("awc.txt");

    SeparateOfficers(write21, write22, write23, fr);
}

Now, let's prepare the test, the test will create a StrinReader that simulates the file from where you are trying to read and its content:

StringReader reader = new StringReader("21\n22\n23\n23");

Additionally, we'll need 3 PrintWriters - similarly, we'll create these on top of StringWriters. We need this in order to easily query them later and see what was written inside of them:

StringWriter sr21 = new StringWriter();
PrintWriter pr21 = new PrintWriter(sr21);

Finally, let's create all of them, run the test, and try to make some assertions:

@Test
public void test() {
    //given
    StringWriter sr21 = new StringWriter();
    StringWriter sr22 = new StringWriter();
    StringWriter sr23 = new StringWriter();
    StringReader reader = new StringReader("21\n22\n23\n23");

    //when
    SeparateOfficers(new PrintWriter(sr21), new PrintWriter(sr22), new PrintWriter(sr23), reader);

    //then
    assertEquals(sr21.toString(), "21\r\n");
    assertEquals(sr22.toString(), "22\r\n");
    assertEquals(sr23.toString(), "23\r\n23\r\n");
}

Basically, what we needed to do was to pass to the tested method, through parameters, some objects that were controlled by the test (these StringWriter and StringReader). They can be called fakes because they implement the Reader and Writer interfaces, but only read/write into a String that you can check later. Though, your code "doesn't know" that it talks to a fake object and not to the real file.

Emanuel Trandafir
  • 1,526
  • 1
  • 5
  • 13