Fresco: NPE in Fresco.initialize(this) in the Application when running Robolectric Unit Test

Created on 1 Mar 2018  路  14Comments  路  Source: facebook/fresco

We use GitHub Issues for bugs.

If you have a non-bug question, please ask on Stack Overflow: http://stackoverflow.com/questions/tagged/fresco

--- Please use this template, and delete everything above this line before submitting your issue ---

Description

Im trying to run a unit test using Robolectric ( testImplementation "org.robolectric:robolectric:3.7.1") and a NPE appears when executing Fresco.initialize(this) in the main Application.
This is the code of the test:

@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {

    @Test
    public void testRecyclerData() {
        final MainActivity activity = Robolectric.setupActivity(MainActivity.class);
        final RecyclerView recyclerView = activity.findViewById(R.id.recycler_view_main_activity);
        final List<Show> list = new ArrayList<Show>();
        list.add(new Show());
        activity.addDataToView(list);
        Assert.assertEquals(1, recyclerView.getAdapter().getItemCount());
    }

}

Here is the stack:

java.lang.NullPointerException
    at java.io.File.<init>(File.java:277)
    at com.facebook.soloader.SoLoader.initImpl(SoLoader.java:198)
    at com.facebook.soloader.SoLoader.init(SoLoader.java:120)
    at com.facebook.soloader.SoLoader.init(SoLoader.java:104)
    at com.facebook.drawee.backends.pipeline.Fresco.initialize(Fresco.java:63)
    at com.facebook.drawee.backends.pipeline.Fresco.initialize(Fresco.java:39)
    at com.sebas.sysfishapp.videofeed.MainApplication.onCreate(MainApplication.java:16)
    at org.robolectric.android.internal.ParallelUniverse.lambda$setUpApplicationState$0(ParallelUniverse.java:204)
    at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:72)
    at org.robolectric.android.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:203)
    at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:333)
    at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:245)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:130)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42)
    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.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:84)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy3.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:748)

Reproduction

100%

Solution

[OPTIONAL: Do you know what needs to be done to address this issue? Ideally, provide a pull request which fixes this issue.]

Additional Information

Most helpful comment

@foghina @BeforeClass is working thanks.
and the method should be static in the TestClass
```
@BeforeClass
public static void before() throws Exception{
SoLoader.setInTestMode();
}

All 14 comments

Try calling SoLoader.setInTestMode() in your test setup (@Before method). We do this in a bunch of our tests as well, see:

https://github.com/facebook/fresco/search?q=setintestmode

Let me know if this fixes the issue. We should probably document this somewhere.

Nop, same error.

@foghina the problem is that the MainApplication extends Application is called before the setUp (@Before) so the SoLoader.setInTestMode() is never been called. Now, I remove the Fresco.Initialize(this) from the MainApplication and set it in the activity and Its working :) but I dont want to call Fresco.initialize(this) in all the activities on my app. Is there any workarround for this situation? Thanks

Hmm, MainApplication#onCreate() shouldn't be called before setUp. Perhaps you can try using @BeforeClass instead?

Hi @sdeira

Could you replace your default Application class with one used only for the tests?

it should be possible using Robolectric: https://stackoverflow.com/questions/21725309/robolectric-not-using-test-application

@sdeira I know its tricky but I solved it with try-catch.
```
try {
Fresco.initialize(this, config);
} catch (Throwable th) {
Log.d("fresco", "error");
}

@foghina @BeforeClass is working thanks.
and the method should be static in the TestClass
```
@BeforeClass
public static void before() throws Exception{
SoLoader.setInTestMode();
}

@BansookNam thanks for the update!

@BansookNam SoLoader is a runtime dependency for Fresco 1.13.0. When using Gradle 5, this is now not included in compilation classpath by default (see migration guide). I had to declare it explicitly:

testImplementation 'com.facebook.soloader:soloader:0.6.0'

@BansookNam @BeforeClass
public static void before() throws Exception{
SoLoader.setInTestMode();
}
this code did not solve the problem for me. try catch did. Is there a way to solve this without using try catch?

@vkotovv Thank you for notice!
@harshmittal29 Did you try implement
testImplementation 'com.facebook.soloader:soloader:0.6.0'
this on your build.gradle? Check vkotovv's comment.

If not working. I have no Idea how to solve 馃槩you may use try catch.

Confirmed that

    @BeforeClass
    public static void setup() {
        SoLoader.setInTestMode();
    }

works for me.

Is there any reason why TestNativeLoader isn't in the 2.0.0 release of Fresco?

This forces consumers to explicitly include the soloader library, which doesn't seem reasonable since Fresco already consumes it so should provide test utilities around it.

TestNativeLoader was added with version 2.1.0 and should be available starting with that version.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rhettor picture rhettor  路  3Comments

goodev picture goodev  路  4Comments

kingty picture kingty  路  4Comments

eldk picture eldk  路  3Comments

satyarths picture satyarths  路  3Comments