Using TDD to develop file traversing code in Java

随声附和 提交于 2019-12-04 04:00:51

问题


I had to implement some code to traverse a directory structure and return a list of files found. The requirements were pretty simple:

  1. Given a base directory, find all files (which are not directories themselves) within.
  2. If a directory is found, repeat step 1 for it.

I wanted to develop the code using TDD. As I started writing the tests, I realized that I was mocking class File, so I could intercept calls to File.isDirectory() and so on. In this way, I was forcing myself to use a solution where I would call that method.

I didn't like it because this test is definitely tightly coupled to the implementation. If I ever change the way in which I ask if a file is a directory, then this test is going to fail even if I keep the contract working. Looking at it as a Private Unit Test made me feel uneasy, for all the reasons expressed on that post. I'm not sure if this is one of those cases where I need to use that kind of testing. On the other hand, I really want to be sure that it returns every file that its not also a directory, traversing the entire structure. To me, that requires a nice, simple, test.

I wanted to avoid having to create a testing directory structure with real testing files "on disk", as I saw it rather clumsy and against some of the best practices that I have read.

Bear in mind that I don't need to do anything with the contents, so tricks like using StringReader instead of FileReader do not apply here. I thought I could do something equivalent, though, like being able to create a directory structure in memory when I set up the test, then tearing it down. I haven't found a way to do it.

How would you develop this code using TDD?

Thanks!


回答1:


The mistake you have made is to mock File. There is a testing anti pattern that assumes that if your class delegates to class X, you must mock class X to test your class. There is also a general rule to be cautious of writing unit tests that do file I/O, because they tend to be too slow. But there is no absolute prohibition on file I/O in unit tests.

In your unit tests have a temporary directory set up and torn down, and create test files and directories within that temporary directory. Yes, your tests will be slower than pure CPU tests, but they will still be fast. JUnit even has support code to help with this very scenario: a @Rule on a TemporaryFolder.

Just this week I implemented, using TDD, some housekeeping code that had to scan through a directory and delete files, so I know this works.




回答2:


As someone who gets very antsy about unit tests that take longer than a few milliseconds to complete, I strongly recommend mocking out the file I/O.

However, I don't think you should mock the File class directly. Instead, look at your use of the File class as the "how", and try to identify the "what". Then codify that with an interface.

For example: you mentioned that one of the things you do is intercept calls to File.isDirectory. Instead of interacting with the File class, what if your code interacted with some implementation of an interface like:

public interface FileSystemNavigator {
    public boolean isDirectory(String path);

    // ... other relevant methods
}

This hides the use of File.isDirectory from the rest of your code, while simultaneously reframing the problem into something more relevant to your program.



来源:https://stackoverflow.com/questions/24566104/using-tdd-to-develop-file-traversing-code-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!