diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index e1e227e595b8cb..5dd6c4a59ba930 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -9,8 +9,6 @@ package com.facebook.react.modules.fresco; -import java.util.HashSet; - import android.content.Context; import android.support.annotation.Nullable; @@ -28,10 +26,12 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.common.ModuleDataCleaner; import com.facebook.react.modules.network.CookieJarContainer; +import com.facebook.react.modules.network.DefaultOkHttpProvider; import com.facebook.react.modules.network.ForwardingCookieHandler; -import com.facebook.react.modules.network.OkHttpClientProvider; import com.facebook.soloader.SoLoader; +import java.util.HashSet; + import okhttp3.JavaNetCookieJar; import okhttp3.OkHttpClient; @@ -154,7 +154,7 @@ public static ImagePipelineConfig.Builder getDefaultConfigBuilder(ReactContext c HashSet requestListeners = new HashSet<>(); requestListeners.add(new SystraceRequestListener()); - OkHttpClient client = OkHttpClientProvider.createClient(); + OkHttpClient client = new DefaultOkHttpProvider().get(); // make sure to forward cookies for any requests via the okHttpClient // so that image requests to endpoints that use cookies still work diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/DefaultOkHttpProvider.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/DefaultOkHttpProvider.java new file mode 100644 index 00000000000000..aa2fa230ce7e06 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/DefaultOkHttpProvider.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.modules.network; + +import android.os.Build; + +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import okhttp3.ConnectionSpec; +import okhttp3.OkHttpClient; +import okhttp3.TlsVersion; + +public class DefaultOkHttpProvider implements OkHttpClientProvider { + + public OkHttpClient get() { + // No timeouts by default + OkHttpClient.Builder client = new OkHttpClient.Builder() + .connectTimeout(0, TimeUnit.MILLISECONDS) + .readTimeout(0, TimeUnit.MILLISECONDS) + .writeTimeout(0, TimeUnit.MILLISECONDS) + .cookieJar(new ReactCookieJarContainer()); + + return enableTls12OnPreLollipop(client).build(); + } + + /** + * On Android 4.1-4.4 (API level 16 to 19) TLS 1.1 and 1.2 are + * available but not enabled by default. The following method + * enables it. + */ + private static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + try { + client.sslSocketFactory(new TLSSocketFactory()); + + ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + List specs = new ArrayList<>(); + specs.add(cs); + specs.add(ConnectionSpec.COMPATIBLE_TLS); + specs.add(ConnectionSpec.CLEARTEXT); + + client.connectionSpecs(specs); + } catch (Exception e) { + FLog.e(ReactConstants.TAG, "Error while enabling TLS 1.2", e); + } + } + return client; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index d4b047994d3938..9f5a48bbc83455 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -9,16 +9,6 @@ package com.facebook.react.modules.network; -import javax.annotation.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - import android.util.Base64; import com.facebook.react.bridge.Arguments; @@ -33,6 +23,16 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nullable; + import okhttp3.Call; import okhttp3.Callback; import okhttp3.CookieJar; @@ -76,10 +76,22 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { /* package */ NetworkingModule( ReactApplicationContext reactContext, @Nullable String defaultUserAgent, - OkHttpClient client, + OkHttpClientProvider httpClientProvider, @Nullable List networkInterceptorCreators) { super(reactContext); + mClient = createOkHttpClient(httpClientProvider, networkInterceptorCreators); + mCookieHandler = new ForwardingCookieHandler(reactContext); + mCookieJarContainer = (CookieJarContainer) mClient.cookieJar(); + mShuttingDown = false; + mDefaultUserAgent = defaultUserAgent; + mRequestIds = new HashSet<>(); + } + + private OkHttpClient createOkHttpClient( + @Nullable OkHttpClientProvider httpClientProvider, + @Nullable List networkInterceptorCreators) { + OkHttpClient client = httpClientProvider == null ? new DefaultOkHttpProvider().get() : httpClientProvider.get(); if (networkInterceptorCreators != null) { OkHttpClient.Builder clientBuilder = client.newBuilder(); for (NetworkInterceptorCreator networkInterceptorCreator : networkInterceptorCreators) { @@ -87,32 +99,35 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { } client = clientBuilder.build(); } - mClient = client; - mCookieHandler = new ForwardingCookieHandler(reactContext); - mCookieJarContainer = (CookieJarContainer) mClient.cookieJar(); - mShuttingDown = false; - mDefaultUserAgent = defaultUserAgent; - mRequestIds = new HashSet<>(); + return client; } /** * @param context the ReactContext of the application * @param defaultUserAgent the User-Agent header that will be set for all requests where the * caller does not provide one explicitly - * @param client the {@link OkHttpClient} to be used for networking + * @param httpClientProvider {@link OkHttpClientProvider} to provider {@link OkHttpClient} */ /* package */ NetworkingModule( ReactApplicationContext context, @Nullable String defaultUserAgent, - OkHttpClient client) { - this(context, defaultUserAgent, client, null); + @Nullable OkHttpClientProvider httpClientProvider) { + this(context, defaultUserAgent, httpClientProvider, null); } /** * @param context the ReactContext of the application */ public NetworkingModule(final ReactApplicationContext context) { - this(context, null, OkHttpClientProvider.createClient(), null); + this(context, null, null, null); + } + + /** + * @param context the ReactContext of the application + * @param httpClientProvider {@link OkHttpClientProvider} to provide {@link OkHttpClient} + */ + public NetworkingModule(final ReactApplicationContext context, @Nullable OkHttpClientProvider httpClientProvider) { + this(context, null, httpClientProvider, null); } /** @@ -123,7 +138,7 @@ public NetworkingModule(final ReactApplicationContext context) { public NetworkingModule( ReactApplicationContext context, List networkInterceptorCreators) { - this(context, null, OkHttpClientProvider.createClient(), networkInterceptorCreators); + this(context, null, null, networkInterceptorCreators); } /** @@ -132,7 +147,7 @@ public NetworkingModule( * caller does not provide one explicitly */ public NetworkingModule(ReactApplicationContext context, String defaultUserAgent) { - this(context, defaultUserAgent, OkHttpClientProvider.createClient(), null); + this(context, defaultUserAgent, new DefaultOkHttpProvider(), null); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java index 5b82aa027a3fad..5c8b3012deb5f9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java @@ -9,79 +9,11 @@ package com.facebook.react.modules.network; -import android.os.Build; - -import com.facebook.common.logging.FLog; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nullable; - -import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; -import okhttp3.TlsVersion; /** - * Helper class that provides the same OkHttpClient instance that will be used for all networking - * requests. + * Interface to provide OkHttpClient instance that will be used for all networking requests. */ -public class OkHttpClientProvider { - - // Centralized OkHttpClient for all networking requests. - private static @Nullable OkHttpClient sClient; - - public static OkHttpClient getOkHttpClient() { - if (sClient == null) { - sClient = createClient(); - } - return sClient; - } - - // okhttp3 OkHttpClient is immutable - // This allows app to init an OkHttpClient with custom settings. - public static void replaceOkHttpClient(OkHttpClient client) { - sClient = client; - } - - public static OkHttpClient createClient() { - // No timeouts by default - OkHttpClient.Builder client = new OkHttpClient.Builder() - .connectTimeout(0, TimeUnit.MILLISECONDS) - .readTimeout(0, TimeUnit.MILLISECONDS) - .writeTimeout(0, TimeUnit.MILLISECONDS) - .cookieJar(new ReactCookieJarContainer()); - - return enableTls12OnPreLollipop(client).build(); - } - - /* - On Android 4.1-4.4 (API level 16 to 19) TLS 1.1 and 1.2 are - available but not enabled by default. The following method - enables it. - */ - public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { - try { - client.sslSocketFactory(new TLSSocketFactory()); - - ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_2) - .build(); - - List specs = new ArrayList<>(); - specs.add(cs); - specs.add(ConnectionSpec.COMPATIBLE_TLS); - specs.add(ConnectionSpec.CLEARTEXT); - - client.connectionSpecs(specs); - } catch (Exception exc) { - FLog.e("OkHttpClientProvider", "Error while enabling TLS 1.2", exc); - } - } - - return client; - } - +public interface OkHttpClientProvider { + OkHttpClient get(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainPackageConfig.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainPackageConfig.java index a5fd60a1573a02..47562ba9b1e252 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainPackageConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainPackageConfig.java @@ -10,31 +10,52 @@ package com.facebook.react.shell; import com.facebook.imagepipeline.core.ImagePipelineConfig; +import com.facebook.react.modules.network.DefaultOkHttpProvider; +import com.facebook.react.modules.network.OkHttpClientProvider; + +import javax.annotation.Nullable; /** * Configuration for {@link MainReactPackage} */ public class MainPackageConfig { - private ImagePipelineConfig mFrescoConfig; + private final @Nullable OkHttpClientProvider mHttpClientProvider; + + private final ImagePipelineConfig mFrescoConfig; private MainPackageConfig(Builder builder) { mFrescoConfig = builder.mFrescoConfig; + mHttpClientProvider = builder.mHttpClientProvider; } public ImagePipelineConfig getFrescoConfig() { return mFrescoConfig; } + public OkHttpClientProvider getHttpClientProvider() { + return mHttpClientProvider != null ? mHttpClientProvider : new DefaultOkHttpProvider(); + } + public static class Builder { private ImagePipelineConfig mFrescoConfig; + private OkHttpClientProvider mHttpClientProvider; public Builder setFrescoConfig(ImagePipelineConfig frescoConfig) { mFrescoConfig = frescoConfig; return this; } + /** + * Option to inject configured OkHttpClient to react-native networking subsystem. + * This will be used only by the fetch networking calls (Fresco library, for eg, will not use this client). + */ + public Builder setOkHttpClientProvider(OkHttpClientProvider okHttpClientProvider) { + this.mHttpClientProvider = okHttpClientProvider; + return this; + } + public MainPackageConfig build() { return new MainPackageConfig(this); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index cb35735d745494..762a7621dd2f68 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -11,6 +11,7 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; + import com.facebook.react.LazyReactPackage; import com.facebook.react.animated.NativeAnimatedModule; import com.facebook.react.bridge.JavaScriptModule; @@ -75,12 +76,13 @@ import com.facebook.react.views.viewpager.ReactViewPagerManager; import com.facebook.react.views.webview.ReactWebViewManager; -import javax.inject.Provider; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import javax.inject.Provider; + /** * Package defining basic modules and view managers. */ @@ -194,7 +196,9 @@ public NativeModule get() { new ModuleSpec(NetworkingModule.class, new Provider() { @Override public NativeModule get() { - return new NetworkingModule(context); + return mConfig == null ? + new NetworkingModule(context) : + new NetworkingModule(context, mConfig.getHttpClientProvider()); } }), new ModuleSpec(NetInfoModule.class, new Provider() { diff --git a/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java index 7b512bc252a5ed..8924d200ec3548 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java @@ -9,10 +9,6 @@ package com.facebook.react.modules.network; -import java.io.InputStream; -import java.util.Arrays; -import java.util.List; - import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; @@ -23,14 +19,6 @@ import com.facebook.react.common.network.OkHttpCallUtil; import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okio.Buffer; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -44,6 +32,19 @@ import org.powermock.modules.junit4.rule.PowerMockRule; import org.robolectric.RobolectricTestRunner; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; + +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okio.Buffer; + import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; @@ -87,8 +88,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); networkingModule.sendRequest( "GET", @@ -119,7 +122,9 @@ public void testFailGetWithInvalidHeadersStruct() throws Exception { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); - NetworkingModule networkingModule = new NetworkingModule(context, "", httpClient); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); + NetworkingModule networkingModule = new NetworkingModule(context, "", clientProvider); List invalidHeaders = Arrays.asList(JavaOnlyArray.of("foo")); @@ -149,7 +154,9 @@ public void testFailPostWithoutContentType() throws Exception { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); - NetworkingModule networkingModule = new NetworkingModule(context, "", httpClient); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); + NetworkingModule networkingModule = new NetworkingModule(context, "", clientProvider); JavaOnlyMap body = new JavaOnlyMap(); body.putString("string", "This is request body"); @@ -211,8 +218,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); JavaOnlyMap body = new JavaOnlyMap(); body.putString("string", "This is request body"); @@ -253,8 +262,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); List headers = Arrays.asList( JavaOnlyArray.of("Accept", "text/plain"), @@ -312,8 +323,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); networkingModule.sendRequest( "POST", "http://someurl/uploadFoo", @@ -377,8 +390,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); networkingModule.sendRequest( "POST", "http://someurl/uploadFoo", @@ -479,9 +494,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); - + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); networkingModule.sendRequest( "POST", "http://someurl/uploadFoo", @@ -541,8 +557,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); networkingModule.initialize(); for (int idx = 0; idx < requests; idx++) { @@ -592,8 +610,10 @@ public Object answer(InvocationOnMock invocation) throws Throwable { OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); when(clientBuilder.build()).thenReturn(httpClient); when(httpClient.newBuilder()).thenReturn(clientBuilder); + OkHttpClientProvider clientProvider = mock(OkHttpClientProvider.class); + when(clientProvider.get()).thenReturn(httpClient); NetworkingModule networkingModule = - new NetworkingModule(mock(ReactApplicationContext.class), "", httpClient); + new NetworkingModule(mock(ReactApplicationContext.class), "", clientProvider); for (int idx = 0; idx < requests; idx++) { networkingModule.sendRequest( diff --git a/ReactAndroid/src/test/java/com/facebook/react/shell/MainPackageConfigTest.java b/ReactAndroid/src/test/java/com/facebook/react/shell/MainPackageConfigTest.java new file mode 100644 index 00000000000000..cccccea4f94f67 --- /dev/null +++ b/ReactAndroid/src/test/java/com/facebook/react/shell/MainPackageConfigTest.java @@ -0,0 +1,27 @@ +package com.facebook.react.shell; + +import com.facebook.react.modules.network.DefaultOkHttpProvider; +import com.facebook.react.modules.network.OkHttpClientProvider; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + +public class MainPackageConfigTest { + + OkHttpClientProvider httpProvider = mock(OkHttpClientProvider.class); + + @Test + public void setOkHttpClientProvider() throws Exception { + MainPackageConfig config = new MainPackageConfig.Builder().setOkHttpClientProvider(httpProvider).build(); + assertEquals(config.getHttpClientProvider(), httpProvider); + } + + @Test + public void shouldReturnDefaultProviderIfNotInjected() throws Exception { + MainPackageConfig config = new MainPackageConfig.Builder().build(); + assertEquals(config.getHttpClientProvider().getClass(), DefaultOkHttpProvider.class); + } + +}