Reece Long
Reece Long

Reputation: 437

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);

}

Upvotes: 2

Views: 2827

Answers (3)

Rog&#233;rio
Rog&#233;rio

Reputation: 16390

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.

Upvotes: 5

You should refactor your method under test so that you're supplying it with an output stream or writer instead of having it open the file itself. This is a good idea generally, even outside the context of unit testing, since it makes the code more reusable; for example, you might want to write the output to a socket or compressed stream.

Upvotes: 1

Rob
Rob

Reputation: 11723

Should probably use a Rule (dumbest name ever, really has nothing to do with rules per se).

Rules for Files in Unit Tests

Upvotes: 0

Related Questions