views:

119

answers:

4

I have a piece of java code which reads strings from a file and creates a map out of the strings. As this code depends on a file, unit testing is clumsy. How does one design such pieces so that code can be unit tested?

One approach that I can think of is, instead of this piece taking a file as an argument it can take an input stream. In actual scenario, pass the file input stream, while unit testing pass an input stream created from a string. But, this looks like an over kill to me. Is there a better way?

+2  A: 

In such cases, I used to create the needed files for test cases, and use them in unit testing. I had a dedicated folder for these files (test data) and setup the test case(s) to take the file appropriate for the test case.

Cătălin Pitiș
Yep, I too would create separate test resource files for my tests to use.
aberrant80
+3  A: 

It's a design error not to provide a function that reads from an InputStream if all you do with the file is read it. Therefore, modify the function to take an InputStream, and provide a wrapper that takes a File. Using a ByteArrayInputStream or a StringInputStream to test it is fine.

phihag
It is funny, you response was the only right answer.
Berlin Brown
A: 

I would suggest either using a dataset (in this case a file) which is dedicated for testing. Otherwise i would use mocking to simulate the access to the external resources. In any case i would tend to extend the coverage of automatic tests as far as possible.

Ralf Edmund
+1  A: 

Look at it this way: no matter how you reorganize your code, the test data has to come from some file. I see 2 variants:

  1. Data is encoded in-place, in one of the .java unit test source code files. It works only for small test data sets. You would need to refactor your code to take input stream and have another wrapper that works with file, as you described.

  2. Test data file. You have to create a project-wide convention where to keep your test data files. Their location may be relative to the jave project location, or under a common test data files root. In any case, it helps to have a utility method that returns a full test data file path given a "logical" file name.

It seems like in your case (just one test, a hundred words) the first solution may be enough. Yes, you would need to refactor the code a little. The second solution is more generic and personally I find it much more practical and applicable.

Some people would say this is not a unit test if it works with data files. Well, it's a matter of definition of "unit test", and is quite irrelevant. If you need to test your code, just find the best / most convenient way for your project.

Igor Krivokon