Reputation: 12999
I am writing a "Total Commander" like application in Java. There is quite obvious file system dependency here.
I want to unit test it. I created directory structure for test purposes, I keep it in known location in SVN repository. It works great so far.
Now, I have a method that should ignore hidden files. How can I go about this? Can I mark file hidden in the SVN somehow?
Other solution would be to make one of the files hidden in the build script before running tests, but I'm afraid this would mark file as modified and always show in a commit dialog.
Any suggestions?
Upvotes: 4
Views: 1519
Reputation: 6317
Essentially, accessing the file system is a big no-no when unit testing. For starters, these tests are slow(er) than your in-system tests, thus reducing the likelihood of you running your tests at a high frequency (such as with every compilation).
Much better if you use an adapter-pattern to abstract away the access to the file system. I'm a .NET developer so my example will be in C#, but I expect you to be able to translate it simply enough:
public class MyManager
{
private readonly IFileAdapter _fileAdapter;
public MyManager(IFileAdapter fileAdapter)
{
_fileAdapter = fileAdapter;
}
}
public interface IFileAdapter
{
public FileStream Open(string fileName);
public string ReadLine(FileStream fileStream);
// More methods...
}
public class FileAdapter : IFileAdapter
{
public FileStream Open(string fileName)
{
return System.Io.File.Open(fileName);
}
public string ReadLine(FileStream fileStream)
{
return File.Open(fileStream);
}
}
Now, as usual, you can mock the file system, as you would any other class, supplying the returned results. Remember - you are not testing Java's IO classes it is assumed that they work. You are only testing your classes (i.e. MyManager, in the example above).
Leave the tests that actually use the file system to your integration / acceptance tests.
Hope this helps, Assaf.
Upvotes: 3
Reputation: 12780
artemb's answer is correct, you can use @Before and @After to create and remove your structure for each test.
Here is some code I use to create a new directory with some files in it, it will create the directory in the systems temp dir, this is important because depending on the machine your tests will run on, you may will not be allowed to create files or dirs somewhere else. (I had to write this code to allow my tests to be executed on our linux integration machine...)
final String tempdir = System.getProperty("java.io.tmpdir");
final String dirname = Long.toHexString(System.currentTimeMillis());
final File dir = new File(tempdir, dirname);
dir.deleteOnExit();
dir.mkdir();
final String path = dir.getAbsolutePath();
assertTrue(dir.exists());
// pre condition, the directory is empty
assertTrue(dir.list().length == 0);
// create temp files in the directory
final int nbFiles = 3;
for (int i = 0; i < nbFiles; i++) {
(File.createTempFile("test", ".txt", dir)).deleteOnExit();
}
BTW you will have to know on what platform you run to be able to create hiden files...
Upvotes: 0
Reputation: 8953
I would prefer to abstract file system, so that my unit-test wouldn't require access to real file system. Of course, this abstraction layer must be tested with real file system, but this allow you to reduce dependency on it.
As for storing hidden files in SVN, I second artemb. You should create all files necessary to test in JUnit set up. Presumably, you should prefer setup per test method (@Before
and @After
). But if you encounter test slowness problems, have a look at @BeforeClass
and @AfterClass
. I consider they can be used with test suites too.
Upvotes: 2
Reputation: 9381
I would put all the initialization of a test directory into the tests themselves. And such a case would be simple:
Upvotes: 10