简体   繁体   中英

Where is getResourceAsStream(“file”) searching when running from a test?

I'm struggling to create a test to verify a ServletListener that loads a properties file. I've tested when running the application that it works fine and it finds the file in the classpath . But I don't know how to create a test for it. My idea is to create a temp file with a test property and then verify the property is put into the System properties . But I always fail to create the file in the right place.

I've tried creating the file in /target/test-classes or directly in the root of the application but it never finds it. Any idea?

This is the code I'm trying to test:

public class PropertyReadingListener implements ServletContextListener {

    public static final String PROFILES_PROPERTIES = "profiles.properties";

    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        Properties propsFromFile = new Properties();
        try {
            propsFromFile.load(getClass().getResourceAsStream(PROFILES_PROPERTIES));
        } catch (final Exception e) {
            log.warn("Unable to find {}, using default profile", PROFILES_PROPERTIES);
        }
        propsFromFile.stringPropertyNames().stream()
            .filter(prop -> System.getProperty(prop) == null)
            .forEach(prop -> System.setProperty(prop, propsFromFile.getProperty(prop)));
    }
}

Thanks.

Where is getResourceAsStream("file") searching when running from a test?

Assuming that you are talking about JUnit ....

Unless you have done something funky, your unit tests will be loaded by the default classloader, and that means that the normal JVM classpath with be searched.

(Junit 4 allows you to use a different classloader: see https://stackoverflow.com/a/9192126/139985 )


But I always fail to create the file in the right place.

It seems that your real problem is understanding how the Java classpath and classpath searching works. If you understand that (and you know what JUnit runner's actual classpath is) then it should be obvious where to put the properties file so that the classloader can find it.

Assuming that you are using maven, put your properties file here:

src/test/resources/foo.properties

The maven resources plugin will place the (possibly filtered) copy of the file in

target/test-classes/foo.properties

The test-classes directory is on the classpath, so you reference the file like this (note the slash in front of the file name):

... getResourceAsStream("/foo.properties");

See Different ways of loading a file as an InputStream

Basically when you do a getClass().getResourceAsStream it looks in the package of that class for the file.. so if your PropertyReadingListener is in com.company.listeners.PropertyReadingListener then it will look in com/company/listeners for the property file.

For testability, I would pass in an InputStream into the listener that way the test can create the input stream in a convienent way and the actual user of the class in code can pass in the InputStream returned from getResourceAsStream

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM