Testing: jUnit's TemporaryFolder
Testing: jUnit's TemporaryFolder
with Simple CSV generator
The problem
Lately I had a question in my head: how to test a method, which output is a file?
Should I divide creation of file from creation of content and test only the latter part?
Well, usually I would like to call a method "generateReport" or retrieveFileByHash(), which encapsulate all file-connected operations and return simple java.io.File. In other words, my service classes looks like this:
- Interface (like ReportGenerator)
- one method
- returns: File
- Concrete class (like DefaultReportGenerator)
- one public implementation of interface method, (like generateReport())
- returns: File
- set of private methods
- returns: whatever is needed to create File
With such services, file's content creation is separated from File creation:
- Interface - ReportGenerator
- method: generateReport()
- returns File
- Concrete Class - DefaultReportGenerator
- method: implementation of generateReport()
- public
- return File
- method: retriveSystemDataFromCurrentMonth()
- private
- returns List of data for report
But since retrieving data is isolated in private method, I cannot simply test it - I would have to call public method anyway and create file, then save it somewhere, confirm its content is valid and proper and then remove it at the end of a test.
The solution
To test such a behaviour, I had to create proper intergration test, since unit tests should not touch file system, according to Michael Feather's. And then, use special thing in jUnit 4 - @Rule TemporaryFolder. It handles all file's operations and guarantees to delete files created through the test.
So to play with this functionality, I created very basic CSV file generator. It works on any entity implementing special proper interface. Let's check integration test.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Rule | |
public TemporaryFolder testFolder = new TemporaryFolder(); | |
private String filePath; | |
private final String FILENAME = "testCsvFile.csv"; | |
@Test | |
public void generate___shouldSucceed() throws IOException { | |
// given | |
filePath = this.generateFilePath(); | |
SystemUser systemUser = new SystemUser(NAME, EMAIL); | |
CsvFileGenerator csvFileGenerator = new SimpleCsvFileGenerator( | |
filePath); | |
// when | |
File file = csvFileGenerator.generate(List.of(systemUser)); | |
// then | |
assertTrue(file.exists()); | |
assertTrue(file.isFile()); | |
assertEquals(FILENAME, file.getName()); | |
List<String> content = Files.lines(Paths.get(file.getAbsolutePath())) | |
.collect(Collectors.toList()); | |
assertEquals(2, content.size()); | |
assertEquals("Identificator,User's name,User's email", content.get(0)); | |
assertEquals("1,Test name,Test email", content.get(1)); | |
} |
Full sample project: https://github.com/toficzak/SimpleCsvGenerator
In the following posts I will try to implement proper abstraction in CSV generator, allowing it to create file's in production environment and mock it in test environment.
Some resources:
- https://stackoverflow.com/questions/3381801/how-do-i-unit-test-saving-file-to-the-disk
- https://www.artima.com/weblogs/viewpost.jsp?thread=126923
- https://garygregory.wordpress.com/2010/01/20/junit-tip-use-rules-to-manage-temporary-files-and-folders/
Komentarze
Prześlij komentarz