22

I want to implement JUnit on a small project I'm working on because I want to learn a little bit about it.

The tutorials that I read all make reference to methods that have a particular output.

In my case my output are files, how can I do this? any simple example? any approach that could help me with this?

The files are raw text files that are build by a void private method.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
Saikios
  • 3,623
  • 7
  • 37
  • 51
  • How do the methods write to the file? If they get a stream you can just give them your own instead of one that points to a file and then compare it. – Amir Rachum Sep 15 '10 at 08:08
  • Whith basic write buffer string inside a web crawler (I press enter but it wrote the message) the code is something like: txtUrlSpecial.write(bigText.charAt(j)); – Saikios Sep 15 '10 at 08:12

5 Answers5

24

You want to get a correct output file for a given set of inputs, and setup a test to call your void method with those inputs, and then compare your validated output file against whats produced by your method. You need to make sure that you have some way of specifying where your method will output to, otherwise your test will be very brittle.

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Test
public void testXYZ() {
    final File expected = new File("xyz.txt");
    final File output = folder.newFile("xyz.txt");
    TestClass.xyz(output);
    Assert.assertEquals(FileUtils.readLines(expected), FileUtils.readLines(output));
}

Uses commons-io FileUtils for convinience text file comparison & JUnit's TemporaryFolder to ensure the output file never exists before the test runs.

Jon Freedman
  • 9,469
  • 4
  • 39
  • 58
  • I like this, but why nobody vote for your answer? :S – Saikios Sep 15 '10 at 08:24
  • 2
    You can always vote for it yourself – Jon Freedman Sep 15 '10 at 09:27
  • eclipse says that org.junit.internal.runners.TestClass is deprecated =( – Saikios Sep 15 '10 at 18:21
  • You should only need to import `junit.framework.Assert` & `org.junit.Test`, are you using JUnit 4? – Jon Freedman Sep 15 '10 at 20:43
  • I guess the usage of this method must be limited to short files, because the output is poorly readable. No information about the line number for example. – Jarekczek Sep 23 '12 at 06:29
  • @Jarekczek : I would suggest that when you find two files that differ you probably want to be comparing them with something other than the stdout from a failed unit test as it's likely there's more than just one difference - don't forget the default behavior of a unit test should be it always passes... – Jon Freedman Mar 17 '21 at 14:41
3

Use junitx.framework.FileAssert class from junit-addons project. Other links:

One of the methods:

assertEquals(java.lang.String message,
             java.io.Reader expected,
             java.io.Reader actual) 
Jarekczek
  • 7,456
  • 3
  • 46
  • 66
  • **protected** static void assertEquals(java.lang.String message, java.io.Reader expected, java.io.Reader actual) – user482745 Oct 23 '15 at 07:55
2

After your methods write the file, in the unit-test you can read the file and verify whether it is written correctly.

Another thing that makes sense is to have your methods split in one that retrieves that data and returns it to the methods that merely writes it to a file. Then you can verify whether the data returned by the first method is fine.

And another plausible approach would be to pass an OutputStream to the method that writes the data. In the "real code" you can pass a FileOutputStream / FileWriter, while in the test-code you can write a mock implementation of OutputStream and check what is being written to it.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
1

If you can't control the method to put the output in a stream, then I'd say you need to refactor your code so that the method receives a stream in the parameter (or in the constructor of its class).

After that, testing is pretty easy - you can just check the stream. Easily testable code usually equals good code.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
Amir Rachum
  • 76,817
  • 74
  • 166
  • 248
  • The problem is that actually it doesn't make one single file, it makes between 3 and 5 files depending on different things. But because I'm really noob with junit I wanted to try it first with one single file to understand it completely. Thanks =D. – Saikios Sep 15 '10 at 08:20
  • @Saikios this is relevant for any number of files :) – Amir Rachum Sep 15 '10 at 08:55
1

Although your question may seem simplistic it does strike to the heart of unit testing, one needs to write well formed code that is testable. This is why some experts advise that one should write the unit test first and then the implementing class.

In your case I suggest you allow your method to execute and create the file(s) expected, following which your unit test(s) can analyse that the files are formed correctly.

  • Thanks, I will have it in mind for next time to first make my unit test :D – Saikios Sep 15 '10 at 08:16
  • The piece of code that writes the whole file is probably too big and complex. JUnit may show if the code still works (no regression) and this is something. However really good Unit tests also help to find what is broken. – Audrius Meškauskas Jun 13 '13 at 19:34