How to handle ordering of @Rule's when they are dependant on eachother

Posted by Lennart Schedin on Stack Overflow See other posts from Stack Overflow or by Lennart Schedin
Published on 2010-04-28T14:30:53Z Indexed on 2010/04/28 14:33 UTC
Read the original article Hit count: 279

Filed under:
|
|

I use embedded servers that run inside Junit test cases. Sometimes these servers require a working directory (for example the Apache Directory server).

The new @Rule in Junit 4.7 can handle these cases. The TemporaryFolder-Rule can create a temporary directory. A custom ExternalResource-Rule can be created for server. But how do I handle if I want to pass the result from one rule into another:

import static org.junit.Assert.assertEquals;
import java.io.*;
import org.junit.*;
import org.junit.rules.*;

public class FolderRuleOrderingTest {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Rule
    public MyNumberServer server = new MyNumberServer(folder);

    @Test
    public void testMyNumberServer() throws IOException {
        server.storeNumber(10);
        assertEquals(10, server.getNumber());
    }

    /** Simple server that can store one number */
    private static class MyNumberServer extends ExternalResource {

        private TemporaryFolder folder;

        /** The actual datafile where the number are stored */
        private File dataFile;

        public MyNumberServer(TemporaryFolder folder) {
            this.folder = folder;
        }

        @Override
        protected void before() throws Throwable {
            if (folder.getRoot() == null) {
                throw new RuntimeException("TemporaryFolder not properly initialized");
            }

            //All server data are stored to a working folder
            File workingFolder = folder.newFolder("my-work-folder");
            dataFile = new File(workingFolder, "datafile");
        }

        public void storeNumber(int number) throws IOException {
            dataFile.createNewFile();
            DataOutputStream out = new DataOutputStream(new FileOutputStream(dataFile));
            out.writeInt(number);
        }

        public int getNumber() throws IOException {
            DataInputStream in = new DataInputStream(new FileInputStream(dataFile));
            return in.readInt();
        }
    }
}

In this code the folder is sent as a parameter into the server so that the server can create a working directory to store data. However this does not work because Junit processes the rules in reverse order as they are defined in the file. The TemporaryFolder Rule will not be executed before the server Rule. Thus the root-folder in TempraryFolder will be null, resulting that any files are created relative to the current working directory.

If I reverse the order of the attributes in my class I get a compile error because I cannot reference a variable before it is defined.

I'm using Junit 4.8.1 (because the ordering of rules was fixed a bit from the 4.7 release)

© Stack Overflow or respective owner

Related posts about junit

Related posts about junit4