Исключение NullPointerException при отражении во время запуска Robolectric - любые подсказки?

Я разрабатываю проект Android на Eclipse, и я пытаюсь переключиться с запуска тестов на эмуляторе / устройстве (который очень медленно) к Robolectric.

Я заменил Android libs на Robolectric, добавил JUnit в путь, изменил тестовый случай на обычный TestCase и добавить предложил @RunWith(RobolectricTestRunner.class) С краткое руководство (внесение необходимых изменений для создания экземпляра моей деятельности вместо того, чтобы полагаться на Тестирование активности Android, чтобы сделать это за меня).

однако, когда я запускаю тест, я получаю:

java.lang.NullPointerException
 at com.xtremelabs.robolectric.RobolectricTestRunner.isInstrumented(RobolectricTestRunner.java:123)
 at com.xtremelabs.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:72)
 at com.xtremelabs.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:57)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
 at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
 at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
 at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
 at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
 at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
 at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
 at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:29)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:40)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:30)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
 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)

это, похоже, связано с этим кодом (от 0.9 tag, так как тег 0.9.1 не имеет его) в RobolectricTestRunner.java:

private static boolean isInstrumented() {
    return RobolectricTestRunner.class.getClassLoader().getClass().getName().contains(RobolectricClassLoader.class.getName());
}

но я не могу понять как, так как это отражение должно работать от самого класса.

кроме того, я мог бы поклясться, что он работал один раз, прежде чем неоднократно терпел неудачу - я удалил кэш robolectric (как было предложено здесь) и заменил JUnit Eclipse на последний (4.8.2), но ничего не изменилось.

какие-то намеки?

обновление: я попытался создать новый, Java (т. е. простой, не Android) тестовый проект, как описано в руководстве быстрого запуска. Однако теперь тестовый прогон жалуется на отсутствие AndroidManifest.XML-код:

java.lang.RuntimeException: java.io.FileNotFoundException: /Users/chester/Documents/workspace/minitruco-android/minitruco-android-robolectric-test/AndroidManifest.xml (No such file or directory)
    at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:245)
    at com.xtremelabs.robolectric.RobolectricTestRunner.setupApplicationState(RobolectricTestRunner.java:215)
    at com.xtremelabs.robolectric.RobolectricTestRunner.internalBeforeTest(RobolectricTestRunner.java:163)
    at com.xtremelabs.robolectric.RobolectricTestRunner.methodBlock(RobolectricTestRunner.java:143)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access0(ParentRunner.java:42)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    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)
Caused by: java.io.FileNotFoundException: /Users/chester/Documents/workspace/minitruco-android/minitruco-android-robolectric-test/AndroidManifest.xml (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:137)
    at java.io.FileInputStream.<init>(FileInputStream.java:96)
    at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:87)
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:178)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at com.xtremelabs.robolectric.RobolectricTestRunner.findResourcePackageName(RobolectricTestRunner.java:255)
    at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:236)
    ... 18 more

Я думаю, что тест должен загрузить файлы из исходного проекта (minitruco-android), который отображается в обоих путь сборки тестового проекта и конфигурация сборки Run/Debug в Eclipse (под записью classpath тестового проекта). Во всяком случае, я скопировал файл из своего исходного тестового проекта (просто для тестирования), но затем он жалуется на R.java (и это действительно должны были быть импортированы из исходного проекта):

java.lang.RuntimeException: java.lang.ClassNotFoundException: caught an exception while obtaining a class file for me.chester.minitruco.test.R
    at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:245)
    at com.xtremelabs.robolectric.RobolectricTestRunner.setupApplicationState(RobolectricTestRunner.java:215)
    at com.xtremelabs.robolectric.RobolectricTestRunner.internalBeforeTest(RobolectricTestRunner.java:163)
    at com.xtremelabs.robolectric.RobolectricTestRunner.methodBlock(RobolectricTestRunner.java:143)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access0(ParentRunner.java:42)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    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)
Caused by: java.lang.ClassNotFoundException: caught an exception while obtaining a class file for me.chester.minitruco.test.R
    at javassist.Loader.findClass(Loader.java:359)
    at com.xtremelabs.robolectric.RobolectricClassLoader.findClass(RobolectricClassLoader.java:60)
    at javassist.Loader.loadClass(Loader.java:311)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
    at com.xtremelabs.robolectric.RobolectricClassLoader.loadClass(RobolectricClassLoader.java:37)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:186)
    at com.xtremelabs.robolectric.RobolectricTestRunner.createResourceLoader(RobolectricTestRunner.java:237)
    ... 18 more
Caused by: javassist.NotFoundException: me.chester.minitruco.test.R
    at javassist.ClassPool.get(ClassPool.java:436)
    at com.xtremelabs.robolectric.AndroidTranslator.onLoad(AndroidTranslator.java:68)
    at javassist.Loader.findClass(Loader.java:340)
    ... 26 more

единственная разница между моей настройкой и быстрым запуском заключается в том, что я сохраняю тестовые источники в тестовом проекте и регулярно источники в обычном проекте (поскольку первые сборки, я бы предположил, что тестовый проект видит регулярные источники - что, конечно, сильно зависит от).

Я использую SoyLatte, но попробовал также Mac OS по умолчанию 1.6 JVM, с теми же результатами.

спасибо.

3 ответов


обычно вам не нужно будет расширять TestCase, но я не думаю, что это должно быть причиной этой проблемы. Не могли бы вы указать источник провала теста?

Что касается упрощенного проекта в вашем обновлении, убедитесь, что Eclipse настроен на установку текущего рабочего каталога в корень основного проекта, а не тестового проекта, поэтому он найдет AndroidManifest.xml и каталог res.


у нас были такие же проблемы в прошлом. То, что работает для нас-это расширение RoboletricTestRunner и предоставление ему RoboletricConfig экземпляр, который знает о местоположении нашего проекта. Таким образом, мне не нужно возиться с любыми конфигурациями запуска с eclipse, он просто работает.

    package ...;

    import java.io.File;

    import org.junit.runners.model.InitializationError;

    import com.xtremelabs.robolectric.RobolectricConfig;
    import com.xtremelabs.robolectric.RobolectricTestRunner;

    public class TestRunner extends RobolectricTestRunner {

        public static final string MAIN_PROJECT_PATH = "../path_to_android_project";

        public TestRunner(Class<?> testClass) throws InitializationError {
             super(testClass, new RobolectricConfig(new File(MAIN_PROJECT_PATH)));
        }
    }

нет необходимости создавать пользовательский RoboelectricTestRunner, просто немного поиграйте с вашими "конфигурациями запуска" на затмение. В конфигурации для запуска тестов перейдите на вкладку classpath и убедитесь, что библиотеки, необходимые для вашего теста, например robolectric-2.2-jar-with-dependencies.jar и android.банку и сам проект находятся в Записей Пользователей и только Java SDK находится в Загрузчик Записи.

затем добавить этот файл:

[project_path] / test / org.robolectric.Конфиг.свойства

 manifest=../AndroidManifest.xml