Мокинг ResourceLoading с помощью JMockit

В моем приложении используется синглтон, в котором хранятся настройки конфигурации. Это код:

private PropertiesSingleton() throws Exception {
    InputStream appstream = this.getClass().getClassLoader()
            .getResourceAsStream("application.properties");
    props = new Properties();
    try {
        props.load(appstream);
    } catch (IOException e) {
        logger.log(Log.FATAL,
                "Cannot find application.properties in classpath.", e);
        throw e;
    }
}

Обычно мое приложение работает внутри контейнера. Для моего unittest я должен сделать application.properties доступным для загрузки. Я пробовал вот так:

@Before
public void init() throws Exception {


    final FileInputStream inStream = new FileInputStream("../path/to/config/application.properties");
    new NonStrictExpectations(ClassLoader.class) {
        {
            String.class.getClassLoader().getResourceAsStream("application.properties"); result = inStream;
        }
    };
}

Тест не запустится, но напечатает эту трассировку стека:

java.lang.VerifyError
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at de.lpm.ejb.archiving.ArchiveHandlerBeanTest$2.<init>(ArchiveHandlerBeanTest.java:50)
at de.lpm.ejb.archiving.ArchiveHandlerBeanTest.init(ArchiveHandlerBeanTest.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

person KFleischer    schedule 21.06.2013    source источник


Ответы (2)


Я считаю, что просто невозможно издеваться над ClassLoader, потому что он там первым. Вы не можете делать что-либо, пока не появится загрузчик классов. Так что попробуйте издеваться над вызывающим, а не над загрузчиком классов.

person KFleischer    schedule 24.06.2013

Я знаю, что это старый, но я решил, что все еще могу вмешаться. Все, что вам нужно сделать, это извлечь это в свой собственный класс Loader:

InputStream appstream = this.getClass().getClassLoader()
        .getResourceAsStream("application.properties");

Подобно этому:

public class MyResourceLoader {
    public InputStream getResource(String location){
        this.getClass().getClassLoader().getResourceAsStream();
    }
}

Затем вам просто нужно использовать новый MyResourceLoader, а затем пометить его как @Mocked в своем тесте. Надеюсь, это поможет.

person LanceP    schedule 01.12.2016