u-ryo's blog

various information for coding...

Category: Retrofit

NullPointerException on Retrofit2 With Robolectric

| Comments

Android ApplicationをRobolectricでtestしていて、 どうにも困ったのでメモです。

状況は、Android Applicationで、 Robolectricを使っていて、 Retrofit2でPOSTしにいく部分(受け手はMockWebServer)のunit testで、 突然NullPointerExceptionになってsubscribeerrorに入ってしまう、というもの。 breakpointで追っていってもcall()で突如NPEに入ってしまって、 具体的にどこでNPEに陥っているのかよく分かりませんでした。 Googleで探してみると、 Stack Overflowにそれらしき投稿があり、 .observeOn(AndroidSchedulers.mainThread())LooperSchedulerなのでここでNPEになる、 だからRxAndroidPluginsregisterSchedulersHook()Schedulers.immediate()してやると良い、 と書いてあって、やったー! と思ったものの、効果なく。

結局そうではなくて、 MockWebServer使っているからhttp://localhost:NNNN/...に requestを改装しているせいなんですけど、 SecurityPolicy絡みのExceptionが裏で出ているようで、 以下のようなShadowを用意して@Config({shadows=...})に 書いてやればそのままですんなり行きました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import android.security.NetworkSecurityPolicy;

import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;

@Implements(NetworkSecurityPolicy.class)
public class ShadowNetworkSecurityPolicy {
    @Implementation
    public static NetworkSecurityPolicy getInstance() {
        try {
            Class<?> shadow = ShadowNetworkSecurityPolicy.class.forName("android.security.NetworkSecurityPolicy");
            return (NetworkSecurityPolicy) shadow.newInstance();
        } catch (Exception e) {
            throw new AssertionError();
        }
    }

    @Implementation
    public boolean isCleartextTrafficPermitted(String hostname) {
        return true;
    }
}

勿論、.subscribeOn(Schedulers.io())に対しては RxJavaHooks.setOnIOScheduler(s -> Schedulers.immediate()); した上で、です。