Search code examples
javaunit-testingjunitjmockit

Java: How do I unit test a method that creates and manipulates a file within the scope of the method?


I'm using JUnit and JMockit to create a unit test method that tests the creation and manipulation of a CSV file. How do I intercept the file that is being created to ensure that is created correctly?

@Test
public void testPersistResultsAsCSV() throws IOException {
    final Long id = new Long(1234l);

    TableRow row = new TableRow();
    row.setValue(317l);
    row.setId(1234l);

    final List<TableRow> rows = new ArrayList<TableRow>();
    rows.add(row);

    final List<TableRow> empty = new ArrayList<TableRow>();

    new Expectations() {
        {
            tableService.findTableRowsById(id, (TableQueryOptions)any);
            result = rows;

            tableService.findTableRowsById(id, (TableQueryOptions)any);
            result = empty;

            fileDataService.saveResultsFile((ResultsFile) any);

        }
    };

    resultsToCsvService.persistResultsAsCSV(id);

}

Solution

  • I am the creator of JMockit, but I will happily say "don't use JMockit" for this.

    You can mock the Java IO classes, but that is almost never a good idea; instead, use a real file on the local filesystem. Your test will be simpler, less fragile, and fast enough (unless you do something bad like reading/writing big files, a large number of them, or accessing a slow remote directory - but none of these should occur in a well-written test).

    When people mock the IO API (ie, File, FileWriter, etc.) they inevitably end up with a test that is tightly coupled to the implementation of the code under test, and therefore complicated and fragile. In practice, it's just better to let the test touch the filesystem; if that makes it an "integration test", so be it.