Android: XmlPullParserFactory.newInstance() creating a null factory
Asked Answered
G

2

0

I'm trying to get XmlPullParser working as it makes a lot more sense than the alternatives. However I'm falling at the first hurdle as the XmlPullParserFactory.newInstance() function is returning a null factory (seen by the debugger). Thus an exception is raised as soon as factory.newPullParser() is called.

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

public class XMLParser
{
    public static void getXML(InputStream in)
            throws XmlPullParserException, IOException {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xpp = factory.newPullParser();

            xpp.setInput(new StringReader("<foo>Hello World!</foo>"));
            int eventType = xpp.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_DOCUMENT) {
                    System.out.println("Start document");
                } else if (eventType == XmlPullParser.START_TAG) {
                    System.out.println("Start tag " + xpp.getName());
                } else if (eventType == XmlPullParser.END_TAG) {
                    System.out.println("End tag " + xpp.getName());
                } else if (eventType == XmlPullParser.TEXT) {
                    System.out.println("Text " + xpp.getText());
                }
                eventType = xpp.next();
            }
            System.out.println("End document");
        } catch (Exception e) {
        }
    }
}

I'm calling this method from a Unit Test. I'm really stumped as to what the issue could be as I've not found any posts that have had issues like this.

Trace report: Full thread dump

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
  at com.company.app.XMLParser.getXmln(XMLParser.java:40)
  at com.company.app.XMLParserTest.setUp(XMLParserTest.java:36)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
  at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
  at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)

"Finalizer@836" daemon prio=8 tid=0x3 nid=NA waiting
  java.lang.Thread.State: WAITING
  at java.lang.Object.wait(Object.java:-1)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler@837" daemon prio=10 tid=0x2 nid=NA waiting
  java.lang.Thread.State: WAITING
  at java.lang.Object.wait(Object.java:-1)
  at java.lang.Object.wait(Object.java:502)
  at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)

"Attach Listener@834" daemon prio=5 tid=0x5 nid=NA runnable
  java.lang.Thread.State: RUNNABLE

"Signal Dispatcher@835" daemon prio=9 tid=0x4 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
Gearwheel answered 25/2, 2016 at 12:1 Comment(5)
It's just returning a newly created instance; no chance of getting null there . Please add Log.wtf("PullParser", e) to your catch clause and post the results.Elbert
The exception being reported is a NullPointerException.Gearwheel
Added a trace report to my question. Hopefully its what you are after.Gearwheel
I was after the stack-trace you find in LogCat when logging the exception like I proposed. Not the whole thread-dump which doesn't anything about the exception itself.Elbert
Tried running it on device and it seems to work correctly. The issue must have something to do with XmlPullParser not working from Unit Tests?Gearwheel
E
0

You cannot unit test components of Android. The JAR file used for compilation only contains method stubs throwing exceptions. Consider a simple test case for your issue

public class UnitTest {
    @Test
    public void instanceNotNull() throws Exception {
        assertNotNull(XmlPullParserFactory.newInstance());
    }
}

Running it without any configuration defined, you'll get a

java.lang.RuntimeException: Method newInstance in org.xmlpull.v1.XmlPullParserFactory not mocked. See http://g.co/androidstudio/not-mocked for details.
    at org.xmlpull.v1.XmlPullParserFactory.newInstance(XmlPullParserFactory.java)
    at ...

When adding

testOptions {
    unitTests.returnDefaultValues = true
}

to your gradle android configuration, you'll find the test just fail on the assertion.

If you want to test with the android library, you need to do it on a device with an instrumented test. So put your test case in the androidTest source set, add

dependencies {
    testCompile 'junit:junit:4.12'
    androidTestCompile 'com.android.support.test:runner:0.4'
}

to the gradle file of your module and run it on a device.

For more information see Testing Concepts and Testing Support Library.

Elbert answered 26/2, 2016 at 9:26 Comment(0)
J
0

Just add this line to your wish list

                (new Thread() {
                    @Override
                    public void run() {
                        try {
                            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                            XmlPullParser xpp = factory.newPullParser();

                            xpp.setInput(new StringReader("<foo>Hello World!</foo>"));
                            int eventType = xpp.getEventType();
                            while (eventType != XmlPullParser.END_DOCUMENT) {
                                if (eventType == XmlPullParser.START_DOCUMENT) {
                                    System.out.println("Start document");
                                } else if (eventType == XmlPullParser.START_TAG) {
                                    System.out.println("Start tag " + xpp.getName());
                                } else if (eventType == XmlPullParser.END_TAG) {
                                    System.out.println("End tag " + xpp.getName());
                                } else if (eventType == XmlPullParser.TEXT) {
                                    System.out.println("Text " + xpp.getText());
                                }
                                eventType = xpp.next();
                            }
                            System.out.println("End document");
                        } catch (Exception e) {
                        }
                    }
                }
                ).start();
Jacobinism answered 17/9, 2018 at 3:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.