package se.leap.bitmaskclient.testutils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.utils.FileHelper.createFile; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getEipDefinitionFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; import android.os.Parcelable; import android.os.ResultReceiver; import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import okhttp3.OkHttpClient; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.FileHelper; import se.leap.bitmaskclient.base.utils.InputStreamHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.connectivity.DnsResolver; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider; import se.leap.bitmaskclient.testutils.matchers.BundleMatcher; import se.leap.bitmaskclient.tor.TorStatusObservable; /** * Created by cyberta on 29.01.18. */ public class MockHelper { @NonNull public static Bundle mockBundle() { final Map fakeBooleanBundle = new HashMap<>(); final Map fakeStringBundle = new HashMap<>(); final Map fakeIntBundle = new HashMap<>(); final Map fakeParcelableBundle = new HashMap<>(); Bundle bundle = mock(Bundle.class); //mock String values in Bundle doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); String value = ((String) arguments[1]); fakeStringBundle.put(key, value); return null; } }).when(bundle).putString(anyString(), anyString()); when(bundle.getString(anyString())).thenAnswer(new Answer() { @Override public String answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return fakeStringBundle.get(key); } }); //mock Boolean values in Bundle doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); Boolean value = ((boolean) arguments[1]); fakeBooleanBundle.put(key, value); return null; } }).when(bundle).putBoolean(anyString(), anyBoolean()); when(bundle.getBoolean(anyString())).thenAnswer(new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return fakeBooleanBundle.get(key); } }); //mock Integer values in Bundle doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); Integer value = ((int) arguments[1]); fakeIntBundle.put(key, value); return null; } }).when(bundle).putInt(anyString(), anyInt()); when(bundle.getInt(anyString())).thenAnswer(new Answer() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return fakeIntBundle.get(key); } }); //mock Parcelable values in Bundle doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); Parcelable value = ((Parcelable) arguments[1]); fakeParcelableBundle.put(key, value); return null; } }).when(bundle).putParcelable(anyString(), any(Parcelable.class)); when(bundle.getParcelable(anyString())).thenAnswer(new Answer() { @Override public Parcelable answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return fakeParcelableBundle.get(key); } }); //mock get when(bundle.get(anyString())).thenAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); if (fakeBooleanBundle.containsKey(key)) { return fakeBooleanBundle.get(key); } else if (fakeIntBundle.containsKey(key)) { return fakeIntBundle.get(key); } else if (fakeStringBundle.containsKey(key)) { return fakeStringBundle.get(key); } else { return fakeParcelableBundle.get(key); } } }); //mock getKeySet when(bundle.keySet()).thenAnswer(new Answer>() { @Override public Set answer(InvocationOnMock invocation) throws Throwable { //this whole approach as a drawback: //you should not add the same keys for values of different types HashSet keys = new HashSet(); keys.addAll(fakeBooleanBundle.keySet()); keys.addAll(fakeIntBundle.keySet()); keys.addAll(fakeStringBundle.keySet()); keys.addAll(fakeParcelableBundle.keySet()); return keys; } }); //mock containsKey when(bundle.containsKey(anyString())).thenAnswer(new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; return fakeBooleanBundle.containsKey(key) || fakeStringBundle.containsKey(key) || fakeIntBundle.containsKey(key) || fakeParcelableBundle.containsKey(key); } }); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; fakeBooleanBundle.remove(key); fakeIntBundle.remove(key); fakeParcelableBundle.remove(key); fakeStringBundle.remove(key); return null; } }).when(bundle).remove(anyString()); return bundle; } public static Intent mockIntent() { Intent intent = mock(Intent.class); final String[] action = new String[1]; final Map fakeExtras = new HashMap<>(); final List categories = new ArrayList<>(); //mock Action in intent doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); action[0] = ((String) arguments[0]); return null; } }).when(intent).setAction(anyString()); when(intent.getAction()).thenAnswer(new Answer() { @Override public String answer(InvocationOnMock invocation) throws Throwable { return action[0]; } }); //mock Bundle in intent extras doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); Bundle value = ((Bundle) arguments[1]); fakeExtras.put(key, value); return null; } }).when(intent).putExtra(anyString(), any(Bundle.class)); when(intent.getBundleExtra(anyString())).thenAnswer(new Answer() { @Override public Bundle answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return (Bundle) fakeExtras.get(key); } }); //mock Parcelable in intent extras doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); Parcelable value = ((Parcelable) arguments[1]); fakeExtras.put(key, value); return null; } }).when(intent).putExtra(anyString(), any(Parcelable.class)); when(intent.getParcelableExtra(anyString())).thenAnswer(new Answer() { @Override public Parcelable answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); String key = ((String) arguments[0]); return (Parcelable) fakeExtras.get(key); } }); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); categories.add(((String) arguments[0])); return null; } }).when(intent).addCategory(anyString()); when(intent.getCategories()).thenAnswer(new Answer>() { @Override public Set answer(InvocationOnMock invocation) throws Throwable { return new HashSet<>(categories); } }); return intent; } public static void mockTextUtils() { mockStatic(TextUtils.class); when(TextUtils.equals(any(CharSequence.class), any(CharSequence.class))).thenAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { CharSequence a = (CharSequence) invocation.getArguments()[0]; CharSequence b = (CharSequence) invocation.getArguments()[1]; if (a == b) return true; int length; if (a != null && b != null && (length = a.length()) == b.length()) { if (a instanceof String && b instanceof String) { return a.equals(b); } else { for (int i = 0; i < length; i++) { if (a.charAt(i) != b.charAt(i)) return false; } return true; } } return false; } }); when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { CharSequence param = (CharSequence) invocation.getArguments()[0]; return param == null || param.length() == 0; } }); } public static ResultReceiver mockResultReceiver(final int expectedResultCode) { ResultReceiver resultReceiver = mock(ResultReceiver.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); int resultCode = (int) arguments[0]; assertEquals("expected resultCode: ", expectedResultCode, resultCode); return null; } }).when(resultReceiver).send(anyInt(), any(Bundle.class)); return resultReceiver; } public static ResultReceiver mockResultReceiver(final int expectedResultCode, final Bundle expectedBundle) { ResultReceiver resultReceiver = mock(ResultReceiver.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); int resultCode = (int) arguments[0]; Bundle bundle = (Bundle) arguments[1]; Set keys = expectedBundle.keySet(); Iterator iterator = keys.iterator(); HashMap expectedIntegers = new HashMap<>(); HashMap expectedStrings = new HashMap<>(); HashMap expectedBooleans = new HashMap<>(); HashMap expectedParcelables = new HashMap<>(); while (iterator.hasNext()) { String key = iterator.next(); Object value = expectedBundle.get(key); if (value instanceof Boolean) { expectedBooleans.put(key, (Boolean) value); } else if (value instanceof Integer) { expectedIntegers.put(key, (Integer) value); } else if (value instanceof String) { expectedStrings.put(key, (String) value); } else if (value instanceof Parcelable) { expectedParcelables.put(key, (Parcelable) value); } } assertThat("expected bundle: ", bundle, new BundleMatcher(expectedIntegers, expectedStrings, expectedBooleans, expectedParcelables)); assertEquals("expected resultCode: ", expectedResultCode, resultCode); return null; } }).when(resultReceiver).send(anyInt(), any(Bundle.class)); return resultReceiver; } public static void mockInputStreamHelper() throws FileNotFoundException { mockStatic(InputStreamHelper.class); when(InputStreamHelper.loadInputStreamAsString(any(InputStream.class))).thenCallRealMethod(); when(InputStreamHelper.getInputStreamFrom(anyString())).thenAnswer(new Answer() { @Override public InputStream answer(InvocationOnMock invocation) throws Throwable { String filename = (String) invocation.getArguments()[0]; return getClass().getClassLoader().getResourceAsStream(filename); } }); when(InputStreamHelper.inputStreamToJson(any(InputStream.class))).thenCallRealMethod(); } public static void mockFileHelper(final File mockedFile) throws FileNotFoundException { mockStatic(FileHelper.class); when(createFile(any(File.class), anyString())).thenReturn(mockedFile); } public static void mockBase64() { mockStatic(android.util.Base64.class); when(android.util.Base64.encodeToString(any(), anyInt())).thenAnswer(invocation -> Arrays.toString(Base64.getEncoder().encode((byte[]) invocation.getArguments()[0]))); } public static void mockRSAHelper() { mockStatic(ConfigHelper.RSAHelper.class); when(ConfigHelper.RSAHelper.parseRsaKeyFromString(anyString())).thenReturn(new RSAPrivateKey() { @Override public BigInteger getPrivateExponent() { return BigInteger.TEN; } @Override public String getAlgorithm() { return "RSA"; } @Override public String getFormat() { return null; } @Override public byte[] getEncoded() { return new byte[0]; } @Override public BigInteger getModulus() { return BigInteger.ONE; } }); } public static void mockConfigHelper(String mockedFingerprint) throws CertificateEncodingException, NoSuchAlgorithmException { mockStatic(ConfigHelper.class); when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint); when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod(); when(ConfigHelper.parseX509CertificatesFromString(anyString())).thenCallRealMethod(); when(ConfigHelper.getProviderFormattedString(any(Resources.class), anyInt())).thenCallRealMethod(); when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod(); when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod(); when(ConfigHelper.isDefaultBitmask()).thenReturn(true); when(ConfigHelper.getDomainFromMainURL(anyString())).thenCallRealMethod(); } public static void mockPreferenceHelper(final Provider providerFromPrefs) { // FIXME use MockSharedPreferences instead of provider mockStatic(PreferenceHelper.class); when(getFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer() { @Override public String answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; switch (key) { case PROVIDER_PRIVATE_KEY: return providerFromPrefs.getPrivateKey(); case PROVIDER_VPN_CERTIFICATE: return providerFromPrefs.getVpnCertificate(); case Provider.KEY: return providerFromPrefs.getDefinition().toString(); case Provider.CA_CERT_FINGERPRINT: return providerFromPrefs.getCaCertFingerprint(); case Provider.CA_CERT: return providerFromPrefs.getCaCert(); case Provider.GEOIP_URL: return providerFromPrefs.getGeoipUrl().toString(); case Provider.MOTD_URL: return providerFromPrefs.getMotdUrl().toString(); case PROVIDER_MOTD: return providerFromPrefs.getMotdJsonString(); } return null; } }); when(getLongFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer() { @Override public Long answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; switch (key) { case PROVIDER_MOTD_LAST_SEEN: return providerFromPrefs.getLastMotdSeen(); case PROVIDER_MOTD_LAST_UPDATED: return providerFromPrefs.getLastMotdUpdate(); } return 0L; } }); when(getStringSetFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer>() { @Override public Set answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; switch (key) { case PROVIDER_MOTD_HASHES: return providerFromPrefs.getMotdLastSeenHashes(); } return null; } }); when(PreferenceHelper.hasKey(anyString())).then(new Answer() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { String key = (String) invocation.getArguments()[0]; if (key!= null && key.contains(providerFromPrefs.getDomain()) && !providerFromPrefs.getDomain().isEmpty()) { key = key.substring(0, key.indexOf(providerFromPrefs.getDomain()) - 1 /* -1 -> "." at the end */); } switch (key) { case PROVIDER_PRIVATE_KEY: return providerFromPrefs.getPrivateKey() != null; case PROVIDER_VPN_CERTIFICATE: return providerFromPrefs.getVpnCertificate() != null; case Provider.KEY: return providerFromPrefs.getDefinition().keys().hasNext(); case Provider.CA_CERT_FINGERPRINT: return providerFromPrefs.getCaCertFingerprint().length() > 1; case Provider.CA_CERT: return providerFromPrefs.getCaCert() != null; case Provider.GEOIP_URL: return !providerFromPrefs.getGeoipUrl().isDefault(); case Provider.MOTD_URL: return !providerFromPrefs.getMotdUrl().isDefault(); case PROVIDER_MOTD: return providerFromPrefs.getMotdJson().keys().hasNext(); } return false; } }); } public static void mockPreferenceHelper(MockSharedPreferences preferences) { mockStatic(PreferenceHelper.class); when(getEipDefinitionFromPreferences()).thenAnswer(new Answer() { @Override public JSONObject answer(InvocationOnMock invocation) throws Throwable { return getEipDefinitionFromPreferences(preferences); } }); } public static void mockTorStatusObservable(@Nullable Throwable exception) throws TimeoutException, InterruptedException { TorStatusObservable observable = TorStatusObservable.getInstance(); mockStatic(TorStatusObservable.class); when(TorStatusObservable.getInstance()).thenAnswer((Answer) invocation -> observable); when(TorStatusObservable.getBootstrapProgress()).thenReturn(0); when(TorStatusObservable.getLastLogs()).thenReturn(new Vector<>()); when(TorStatusObservable.getLastTorLog()).thenReturn(""); when(TorStatusObservable.getLastSnowflakeLog()).thenReturn(""); AtomicBoolean waitUntilSuccess = new AtomicBoolean(false); when(TorStatusObservable.getProxyPort()).thenAnswer((Answer) invocation -> { if (waitUntilSuccess.get()) { return 8118; } return -1; }); when(TorStatusObservable.getStatus()).thenAnswer((Answer) invocation -> { if (waitUntilSuccess.get()) { return TorStatusObservable.TorStatus.ON; } return TorStatusObservable.TorStatus.OFF; }); when(TorStatusObservable.getSnowflakeStatus()).thenAnswer((Answer) invocation -> { if (waitUntilSuccess.get()) { return TorStatusObservable.SnowflakeStatus.STARTED; } return TorStatusObservable.SnowflakeStatus.STOPPED; }); if (exception != null) { when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenThrow(exception); } else { when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenAnswer((Answer) invocation -> { waitUntilSuccess.set(true); return true; }); } } public static void mockProviderObservable(Provider provider) { ProviderObservable observable = ProviderObservable.getInstance(); observable.updateProvider(provider); mockStatic(ProviderObservable.class); when(ProviderObservable.getInstance()).thenAnswer((Answer) invocation -> observable); } public static void mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException { BackendMockProvider.provideBackendResponsesFor(errorCase); } public static OkHttpClientGenerator mockClientGenerator(boolean resolveDNS) throws UnknownHostException { OkHttpClientGenerator mockClientGenerator = mock(OkHttpClientGenerator.class); OkHttpClient mockedOkHttpClient = mock(OkHttpClient.class); DnsResolver mockedDnsResolver = mock(DnsResolver.class); when(mockClientGenerator.initCommercialCAHttpClient(any(JSONObject.class), anyInt())).thenReturn(mockedOkHttpClient); when(mockClientGenerator.initSelfSignedCAHttpClient(anyString(), anyInt(), any(JSONObject.class))).thenReturn(mockedOkHttpClient); if (resolveDNS) { when(mockedDnsResolver.lookup(anyString())).thenReturn(new ArrayList<>()); } else { when(mockedDnsResolver.lookup(anyString())).thenThrow(new UnknownHostException()); } return mockClientGenerator; } public static OkHttpClientGenerator mockClientGenerator() throws UnknownHostException { return mockClientGenerator(true); } public static Resources mockResources(InputStream inputStream) throws IOException, JSONException { Resources mockedResources = mock(Resources.class, RETURNS_DEEP_STUBS); JSONObject errorMessages = new JSONObject(TestSetupHelper.getInputAsString(inputStream)); when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask")); when(mockedResources.getString(R.string.server_unreachable_message)). thenReturn(errorMessages.getString("server_unreachable_message")); when(mockedResources.getString(R.string.error_security_pinnedcertificate)). thenReturn(errorMessages.getString("error.security.pinnedcertificate")); when(mockedResources.getString(eq(R.string.malformed_url), anyString())). thenReturn(String.format(errorMessages.getString("malformed_url"), "Bitmask")); when(mockedResources.getString(eq(R.string.certificate_error), anyString())). thenReturn(String.format(errorMessages.getString("certificate_error"), "Bitmask")); when(mockedResources.getString(R.string.error_srp_math_error_user_message)). thenReturn(errorMessages.getString("error_srp_math_error_user_message")); when(mockedResources.getString(R.string.error_bad_user_password_user_message)). thenReturn(errorMessages.getString("error_bad_user_password_user_message")); when(mockedResources.getString(R.string.error_not_valid_password_user_message)). thenReturn(errorMessages.getString("error_not_valid_password_user_message")); when(mockedResources.getString(R.string.error_client_http_user_message)). thenReturn(errorMessages.getString("error_client_http_user_message")); when(mockedResources.getString(R.string.error_io_exception_user_message)). thenReturn(errorMessages.getString("error_io_exception_user_message")); when(mockedResources.getString(R.string.error_json_exception_user_message)). thenReturn(errorMessages.getString("error_json_exception_user_message")); when(mockedResources.getString(R.string.error_no_such_algorithm_exception_user_message)). thenReturn(errorMessages.getString("error_no_such_algorithm_exception_user_message")); when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask")); when(mockedResources.getString(eq(R.string.warning_corrupted_provider_cert), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_cert"), "Bitmask")); when(mockedResources.getString(eq(R.string.warning_expired_provider_cert), anyString())). thenReturn(String.format(errorMessages.getString("warning_expired_provider_cert"), "Bitmask")); when(mockedResources.getString(eq(R.string.setup_error_text), anyString())). thenReturn(String.format(errorMessages.getString("setup_error_text"), "Bitmask")); when(mockedResources.getString(eq(R.string.setup_error_text_custom), anyString())). thenReturn(String.format(errorMessages.getString("setup_error_text_custom"), "RiseupVPN")); when(mockedResources.getString(R.string.app_name)). thenReturn("Bitmask"); when(mockedResources.getString(eq(R.string.error_tor_timeout), anyString())). thenReturn(String.format(errorMessages.getString("error_tor_timeout"), "Bitmask")); when(mockedResources.getString(eq(R.string.error_network_connection), anyString())). thenReturn(String.format(errorMessages.getString("error_network_connection"), "Bitmask")); return mockedResources; } public static Context mockContext() throws PackageManager.NameNotFoundException { Context context = mock(Context.class, RETURNS_DEEP_STUBS); when(context.getPackageName()).thenReturn("se.leap.bitmaskclient"); PackageInfo mockPackageInfo = new PackageInfo(); mockPackageInfo.versionName = "0.9.10"; when(context.getPackageManager().getPackageInfo(anyString(), anyInt())).thenReturn(mockPackageInfo); return context; } }