pornhub.com tube8.com youporn.com

How to read input files in maven junit

Sometimes we need to put unit test data into plain text files. For example, assume we want to test a parser using a json string as the test data. If we put the json string as a constant string in the java code, we end up with a lot of error-prone escaping characters. In that case, we may want to put the test string into a file as a resource and read the string from the file in junit.

In maven, we need to put the resource file in src/test/resources. Let me create a demo from scratch.

> mvn archetype:create -DgroupId=org.fuyun -DartifactId=junitresdemo
> find .
.
./junitresdemo
./junitresdemo/pom.xml
./junitresdemo/src
./junitresdemo/src/test
./junitresdemo/src/test/java
./junitresdemo/src/test/java/org
./junitresdemo/src/test/java/org/fuyun
./junitresdemo/src/test/java/org/fuyun/AppTest.java
./junitresdemo/src/main
./junitresdemo/src/main/java
./junitresdemo/src/main/java/org
./junitresdemo/src/main/java/org/fuyun
./junitresdemo/src/main/java/org/fuyun/App.java

> cd junitresdemo
> mkdir -p src/test/resources
> vi src/test/resources/myres.txt
> cat src/test/resources/myres.txt
test1=testdata

As you can see, I put my test data as a key-value pair in a property file. If your test data contains special characters such as escape char, you’d better handle file reading by yourself instead of using Properties as I am going to show.

Then I modify the automatically generated test code src/test/java/org/fuyun/AppTest.java as follows.

package org.fuyun;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.io.InputStream;
import java.util.Properties;

public class AppTest extends TestCase {
    public AppTest( String testName ) {
        super( testName );
    }

    public static Test suite() {
        return new TestSuite( AppTest.class );
    }

    public void testApp() throws java.io.IOException {
        InputStream in =
            getClass().getClassLoader().getResourceAsStream("myres.txt");
        Properties p = new Properties();
        p.load(in);
        String mystr = p.getProperty("test1");
        assertEquals("testdata", mystr);
    }
}

To read the property file, we need to use getResourceAsStream. Actually this is why I want to write this blog. If you search on web, you may find that people talk about you can load the file using Class.getResourceAsStream(). So, I am supposed to write the line as

        InputStream in = getClass().getResourceAsStream("myres.txt");

It can compile. But the test will fail. The InputStream variable in will be null, i.e., it cannot find myres.txt. Why? Why do we have to use the method defined in ClassLoader?

The difference between Class.getResourceAsStream and ClassLoader.getResourceAsStream is that Class.getResourceAsStream attempts to first resolve the file name by appending the package prefix (org/fuyun/) if the file name is not an absolute path, otherwise removes the leading “/” if the path is absolute. Then, it calls the ClassLoader’s getResourceAsStream to load the resolved file name. This is documented here.

For example, if I do the following hack, the test will pass temporarily.

> mv target/test-classes/myres.txt target/test-classes/org/fuyun/.
> mvn test

But to really fix it, we should revise the line by adding a leading “/” in the file name as follows.

        InputStream in = getClass().getResourceAsStream("/myres.txt");

On the other hand, if you use ClassLoader.getResourceAsStream, the leading “/” will make it unable to find the file.

programming

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

One Response to “How to read input files in maven junit”

Leave Comment

(required)

(required)