Xamarin forms app throws a null exception when creating StandardKernel - android

I created with VS2017 a cross-platform App(Xamarin Forms) with the template set to Blank App, Platform Android, UI Tech Xamarin.Forms, Code Sharing .NET Standard. All builds and runs and displays "Welcome to Xamarin Froms".
I added the Portable.Ninject package to both the .NET standard PCL project and the Android project.
Created the following Test class and interface
public class Test : ITest
{
public string name { get; set; }
}
public interface ITest
{
string name { get; set; }
}
A NinjectModule class
public class modules : NinjectModule
{
public override void Load()
{
Bind<ITest>().To<Test>();
}
}
and in the class App:Application and added kernel creation in the constructor
public App ()
{
InitializeComponent();
var settings = new NinjectSettings();
settings.LoadExtensions = false;
var mods = new modules();
var kernel = new StandardKernel(mods);
var test = kernel.Get<ITest>();
MainPage = new App12.MainPage();
}
When ran an ArgumentNULLException. Parameter name:path1 occurs at the new StanardKernel( new modules() ).
Any help will be appreciated. I have tried the Ninject Nuget package, creating the StandardKernel in the android project MainActivity:Oncreate, deleting packages, bin and obj folders ... all with the same result
Addition :- Separated the instantiate of modules class the following is watch window. Shouldn't the Binding list have a count of 1 ?
- mods {App12.modules} App12.modules
- base {Ninject.Modules.NinjectModule} Ninject.Modules.NinjectModule
+ base {Ninject.Syntax.BindingRoot} Ninject.Syntax.BindingRoot
+ Bindings Count = 0 System.Collections.Generic.List<Ninject.Planning.Bindings.IBinding>
Kernel (null) Ninject.IKernel
Name "App12.modules" string
+ Non-public members

You should add a NinjaSettings object with LoadExtensions set to false to the StandardKernel constructor.
public App()
{
InitializeComponent();
var settings = new NinjectSettings();
settings.LoadExtensions = false;
var kernel = new StandardKernel(settings, new modules());
var test = kernel.Get<ITest>();
MainPage = new App12.MainPage();
}

Related

How to use dependecy injection in flutter?

I wan to use di. in flutter and I add this https://pub.dartlang.org/packages/di packages my project and I started to read this https://webdev.dartlang.org/angular/guide/dependency-injection article, but I don't fully understand.
So it's ok:
use #Injectable() annotation on services class(e.g: MyServices), but how to inject other class?
For example I would like to similar:
class MyClass{
//some variable
var asd = MyService.asd; //need inject var.
//maybe use injector.get(MyService).asd;
//but how add injector? (I don't add across constructor)
MyService.oneMethod;//need inject method
}
main(){
var injector = new ModuleInjector([new Module()
..bind(MyService)
]);
}
The point is, I don't want to use a constructor. I want to directly use injector. This is possible in flutter/dart?
There is a Flutter-compatible dependency injection framework that Google recently open-sourced. It is available here: https://github.com/google/inject.dart
This project provides static compile-time dependency injection, rather than relying on reflection to inject dependencies at run-time. If you are familiar with Dagger, it appears to be quite similar.
It's worth noting - this is not an official Google or Dart team project. At the time of writing, there is little documentation and it is currently considered a developer preview.
Angulars DI package can't be used independent of Angular.
The di package is quite outdated and depends on dart:mirrors which isn't available in Flutter
There seems to be a new DI package work in progress which is supposed to replace Angulars built-in DI and should also be useable standalone in Flutter or server-side applications, but there is no pre-release or source code available yet.
update
The announced DI package was delayed indefinitely.
If you want to use a class as a Singleton, from what I saw, the common usecase is to use a factory constructor.
How do you build a Singleton in Dart?
Never had to use any dependency injection system with Flutter for now.
Hello what about something like this? Very simple implementation, Injector itself is singleton and also added classes into it. Of course can be extended very easily. If you are looking for something more sophisticated check this package: https://pub.dartlang.org/packages/flutter_simple_dependency_injection
void main() {
Injector injector = Injector();
injector.add(() => Person('Filip'));
injector.add(() => City('New York'));
Person person = injector.get<Person>();
City city = injector.get<City>();
print(person.name);
print(city.name);
}
class Person {
String name;
Person(this.name);
}
class City {
String name;
City(this.name);
}
typedef T CreateInstanceFn<T>();
class Injector {
static final Injector _singleton = Injector._internal();
final _factories = Map<String, dynamic>();
factory Injector() {
return _singleton;
}
Injector._internal();
String _generateKey<T>(T type) {
return '${type.toString()}_instance';
}
void add<T>(CreateInstanceFn<T> createInstance) {
final typeKey = _generateKey(T);
_factories[typeKey] = createInstance();
}
T get<T>() {
final typeKey = _generateKey(T);
T instance = _factories[typeKey];
if (instance == null) {
print('Cannot find instance for type $typeKey');
}
return instance;
}
}
I was facing the same issue here so I created a dart package specifically for Flutter. It relies on factory methods rather than the mirrors api so it works in flutter. While still using a familiar IOC pattern. Hope this helps!
https://pub.dartlang.org/packages/flutter_simple_dependency_injection
import 'package:flutter_simple_dependency_injection/injector.dart';
void main() {
final injector = Injector.getInjector();
injector.map(Logger, (i) => new Logger(), isSingleton: true);
injector.map(String, (i) => "https://api.com/", key: "apiUrl");
injector.map(SomeService, (i) => new SomeService(i.get(Logger), i.get(String, "apiUrl")));
injector.get(SomeService).doSomething();
// passing in the [SomeService] as a generic parameter strongly types the return object.
injector.get<SomeService>(SomeService).doSomething();
}
class Logger {
void log(String message) => print(message);
}
class SomeService {
final Logger _logger;
final String _apiUrl;
SomeService(this._logger, this._apiUrl);
void doSomething() {
_logger.log("Doing something with the api at '$_apiUrl'");
}
}
This package ioc_container is a Dart Ioc Container. Technically, it's not an injector because it doesn't automate injection with anything like reflection. However, it does simplify and organize the process of injecting dependencies within your factories. Here is the code.
Code here
import 'package:meta/meta.dart';
class ServiceDefinition<T> {
bool isSingleton;
T Function(IocContainer container) factory;
ServiceDefinition(this.isSingleton, this.factory);
}
class IocContainer {
#visibleForTesting
final Map<Type, ServiceDefinition> serviceDefinitionsByType;
#visibleForTesting
final Map<Type, Object> singletons;
IocContainer(this.serviceDefinitionsByType, this.singletons);
///Get an instance of your dependency
T get<T>() => singletons.containsKey(T)
? singletons[T] as T
: serviceDefinitionsByType.containsKey(T)
? (serviceDefinitionsByType[T]!.isSingleton
? singletons.putIfAbsent(
T,
() =>
serviceDefinitionsByType[T]!.factory(this) as Object) as T
: serviceDefinitionsByType[T]!.factory(this))
: throw Exception('Service not found');
}
///A builder for creating an [IocContainer].
class IocContainerBuilder {
final Map<Type, ServiceDefinition> _serviceDefinitionsByType = {};
///Throw an error if a service is added more than once. Set this to true when
///you want to add mocks to set of services for a test.
final bool allowOverrides;
IocContainerBuilder({this.allowOverrides = false});
///Add a factory to the container.
void addServiceDefinition<T>(
///Add a factory and whether or not this service is a singleton
ServiceDefinition<T> serviceDefinition) {
if (_serviceDefinitionsByType.containsKey(T)) {
if (allowOverrides) {
_serviceDefinitionsByType.remove(T);
} else {
throw Exception('Service already exists');
}
}
_serviceDefinitionsByType.putIfAbsent(T, () => serviceDefinition);
}
///Create an [IocContainer] from the [IocContainerBuilder].
///This will create an instance of each singleton service and store it
///in an immutable list unless you specify [isLazy] as true.
IocContainer toContainer(
{
///If this is true the services will be created when they are requested
///and this container will not technically be immutable.
bool isLazy = false}) {
if (!isLazy) {
final singletons = <Type, Object>{};
final tempContainer = IocContainer(_serviceDefinitionsByType, singletons);
_serviceDefinitionsByType.forEach((type, serviceDefinition) {
if (serviceDefinition.isSingleton) {
singletons.putIfAbsent(
type, () => serviceDefinition.factory(tempContainer));
}
});
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
Map<Type, Object>.unmodifiable(singletons));
}
return IocContainer(
Map<Type, ServiceDefinition>.unmodifiable(_serviceDefinitionsByType),
<Type, Object>{});
}
}
extension Extensions on IocContainerBuilder {
///Add a singleton object dependency to the container.
void addSingletonService<T>(T service) =>
addServiceDefinition(ServiceDefinition(true, (i) => service));
void addSingleton<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(true, factory));
void add<T>(T Function(IocContainer container) factory) =>
addServiceDefinition(ServiceDefinition(false, factory));
}

Unit test Android, getString from resource

I am trying to do an unit test for an android app and I need to get a string from res.string resources. The class that I want to test is a POJO class. I am doing the app in two languages, due to this, I need to get a string from resource. The problem is that I cannot get the context or the activity, is possible? I know that with Instrumentation test I can do it, but I need to test some functions (white box test) before to do the instrumentation test (black box test).
This is the function that I have to test:
public void setDiaByText(String textView) {
getll_diaSeleccionado().clear();
if (textView.contains(context.getResources().getString(R.string.sInicialLunes))) {
getll_diaSeleccionado().add(0);
getIsSelectedArray()[0] = true;
getI_idiaSeleccionado()[0] =1;
} else
{
getIsSelectedArray()[0] = false;
getI_idiaSeleccionado()[0] =0;
}
}
And this is the test:
#Test
public void setDiaByTextView() {
String texto = "L,M,X,J,V,S,D";
alertaPOJO.setDiaByText(texto);
assertEquals(alertaPOJO.getIsSelectedArray()[0], true);
assertEquals(alertaPOJO.getI_idiaSeleccionado()[0], 1);
}
It crash when try to do context.getResources().getString(R.string.sInicialLunes))
If I put 'Mon' instead of context.getResources().getString(R.string.sInicialLunes)) or 'L' it work perfectly so, is possible to get the context or the activity in order to access to resource folder?
I am testing with Mockito and the setUp function is:
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = Mockito.mock(Alerta.class);
Mockito.when(mContext.getApplicationContext()).thenReturn(mContext);
alertaPOJO = new AlertaPOJO();
}
Thanks
If you are using Context only for obtaining String resource, I would go by mocking only getResources().getString() part like this (see JUnit4 notation):
#RunWith(MockitoJUnitRunner.class)
public class AlertaPOJOTest {
#Mock
Context mMockContext;
#Test
public void setDiaByTextView() {
String texto = "L,M,X,J,V,S,D";
when(mMockContext.getString(R.string.sInicialLunes))
.thenReturn(INITIAL_LUNES);
alertaPOJO.setDiaByText(texto);
assertEquals(alertaPOJO.getIsSelectedArray()[0], true);
assertEquals(alertaPOJO.getI_idiaSeleccionado()[0], 1);
}
}
There are many reasons to stay with JVM tests, most important one, they are running quicker.
Untested: would it work to use the below, and probably targetContext?
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
You don't have a real android Context while you are using JVM unit test. For your case, maybe you can try Android Instrumentation Test, typically it is implemented in the "androidTest" directory of your project.
If you use MockK it's the same.
#RunWith(AndroidJUnit4::class)
class YourClassUnitTest : TestCase() {
#MockK
private lateinit var resources: Resources
#Before
public override fun setUp() {
MockKAnnotations.init(this)
}
#Test
fun test() {
every {
resources.getQuantityString(R.plurals.age, YEARS, YEARS)
} returns AGE
every {
resources.getString(
R.string.surname,
SURNAME
)
} returns TITLE
// Assume you test this method that returns data class
// (fields are calculated with getQuantityString and getString)
val data = getData(YEARS, SURNAME)
assertEquals(AGE, data.age)
assertEquals(TITLE, data.title)
}
companion object {
const val YEARS = 10
const val AGE = "$YEARS years"
const val SURNAME = "Johns"
const val TITLE = "Mr. $SURNAME"
}
}
See also Skip a parameter in MockK unit test, Kotlin to get a result of string resources for any data.

DexFile in 2.0 versions of Android Studio and Gradle

I am using the following code to instantiate all the classes included in a certain package.
DexFile df = new DexFile(getPackageCodePath());
for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
String className = iter.nextElement();
if (className.contains(packageName) && !className.contains("$")) {
myClasses.add(Class.forName(className).newInstance());
}
}
Unfortunately it is not working properly anymore. Since Android Studio 2 and Gradle 2.0.0, the DexFile entries no longer include all the classes within the app but only the classes belonging to the com.android.tools package.
Is this a known issue?
Looks like this issue is related to the new InstantRun feature in the Android Plugin for Gradle 2.0.0.
getPackageCodePath() gets a String pointing towards the base.apk file in the Android file system. If we unzip that apk we can find one or several .dex files inside its root folder. The entries obtained from the method df.entries() iterates over the .dex files found in that root folder in order to obtain all of its compiled classes.
However, if we are using the new Android Plugin for Gradle, we will only find the .dex related to the android runtime and instant run (packages com.tools.android.fd.runtime, com.tools.android.fd.common and com.tools.android.tools.ir.api). Every other class will be compiled in several .dex files, zipped into a file called instant-run.zip and placed into the root folder of the apk.
That's why the code posted in the question is not able to list all the classes within the app. Still, this will only affect Debug builds since the Release ones don't feature InstantRun.
To access all DexFiles you can do this
internal fun getDexFiles(context: Context): List<DexFile> {
// Here we do some reflection to access the dex files from the class loader. These implementation details vary by platform version,
// so we have to be a little careful, but not a huge deal since this is just for testing. It should work on 21+.
// The source for reference is at:
// https://android.googlesource.com/platform/libcore/+/oreo-release/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
val classLoader = context.classLoader as BaseDexClassLoader
val pathListField = field("dalvik.system.BaseDexClassLoader", "pathList")
val pathList = pathListField.get(classLoader) // Type is DexPathList
val dexElementsField = field("dalvik.system.DexPathList", "dexElements")
#Suppress("UNCHECKED_CAST")
val dexElements = dexElementsField.get(pathList) as Array<Any> // Type is Array<DexPathList.Element>
val dexFileField = field("dalvik.system.DexPathList\$Element", "dexFile")
return dexElements.map {
dexFileField.get(it) as DexFile
}
}
private fun field(className: String, fieldName: String): Field {
val clazz = Class.forName(className)
val field = clazz.getDeclaredField(fieldName)
field.isAccessible = true
return field
}
for get all dex files of an app use below method.
public static ArrayList<DexFile> getMultiDex()
{
BaseDexClassLoader dexLoader = (BaseDexClassLoader) getClassLoader();
Field f = getField("pathList", getClassByAddressName("dalvik.system.BaseDexClassLoader"));
Object pathList = getObjectFromField(f, dexLoader);
Field f2 = getField("dexElements", getClassByAddressName("dalvik.system.DexPathList"));
Object[] list = getObjectFromField(f2, pathList);
Field f3 = getField("dexFile", getClassByAddressName("dalvik.system.DexPathList$Element"));
ArrayList<DexFile> res = new ArrayList<>();
for(int i = 0; i < list.length; i++)
{
DexFile d = getObjectFromField(f3, list[i]);
res.add(d);
}
return res;
}
//------------ other methods
public static ClassLoader getClassLoader()
{
return Thread.currentThread().getContextClassLoader();
}
public static Class<?> getClassByAddressName(String classAddressName)
{
Class mClass = null;
try
{
mClass = Class.forName(classAddressName);
} catch(Exception e)
{
}
return mClass;
}
public static <T extends Object> T getObjectFromField(Field field, Object arg)
{
try
{
field.setAccessible(true);
return (T) field.get(arg);
} catch(Exception e)
{
e.printStackTrace();
return null;
}
}

Dagger 2: No implementation generated for component interface

I have created a demo Android Lib project and used dagger 2.0 with the following steps:
Added the following jars to /libs folder:
dagger-2.0.jar
dagger-compiler-2.0.jar
dagger-producers-2.0-beta.jar
guava-18.0.jar
javawriter-2.5.1.jar
javax.annotation-api-1.2.jar
javax.inject-1.jar
Project -> Properties -> Java Compiler -> Annotation Processing (Enabled annotation processing)
Project -> Properties -> Java Compiler -> Annotation Processing - Factory path: Added all the above mentioned jars.
Created the following classes:
public class Car {
private Engine engine;
#Inject
public Car(Engine engine) {
this.engine = engine;
}
public String carDetails(){
String engineName = this.engine.getName();
int engineNumber = this.engine.getNumber();
return "This car has the following details: \n" + engineName + "----" + engineNumber;
}
}
public interface Engine {
public String getName();
public int getNumber();
}
public class Toyota implements Engine{
#Override
public String getName() {
return "This is toyota engine";
}
#Override
public int getNumber() {
return 1234567890;
}
}
#Component(modules = EngineModule.class)
public interface EngineComponent {
void inject();
}
#Module
public class EngineModule {
public EngineModule(DemoApplication demoApplication) {
}
#Provides
Engine provideEngine(){
return new Toyota();
}
}
But inside /.apt-generated folder there are only two files:
Car_Factory.java EngineModule_ProvideEngineFactory.java
DaggerEngineComponent.java is not there for me to build the component.
Could someone please help?
I'm guessing the annotation processor is encountering an error and Eclipse is not showing you the log. If you have log output in the Output view, you may want to paste that into the question.
Specifically, I think it's erroring out on void inject(), which isn't a format descibed in the #Component docs. Those docs describe three types of methods:
Parameterless factory methods that return an injectable type Dagger creates and injects, like Engine createEngine(), or
Single-parameter void methods that receive an instance created elsewhere and apply method and field injection, like void injectEngine(Engine) or Engine injectEngine(Engine).
Subcomponent-returning methods that combine your Component's bindings with those from another module.
Because your void inject() doesn't match any of those formats, Dagger is likely erroring out and refusing to create a DaggerEngineComponent.

How to detect whether android app is running UI test with Espresso

I am writing some Espresso tests for Android. I am running in the the following problem:
In order for a certain test case to run properly, I need to disable some features in the app. Therefore, in my app, I need to detect whether I am running Espresso test so that I can disable it. However, I don't want to use BuildConfig.DEBUG to because I don't want those features to be disabled in a debug build. Also, I would like to avoid creating a new buildConfig to avoid too many build variants to be created (we already have a lot of flavors defined).
I was looking for a way to define buildConfigField for test but I couldn't find any reference on Google.
Combining Commonsware comment + Comtaler's solution here's a way to do it for any test class using the Espresso framework.
private static AtomicBoolean isRunningTest;
public static synchronized boolean isRunningTest () {
if (null == isRunningTest) {
boolean istest;
try {
// "android.support.test.espresso.Espresso" if you haven't migrated to androidx yet
Class.forName ("androidx.test.espresso.Espresso");
istest = true;
} catch (ClassNotFoundException e) {
istest = false;
}
isRunningTest = new AtomicBoolean (istest);
}
return isRunningTest.get();
}
Combined with CommonsWare's comment. Here is my solution:
I defined an AtomicBoolean variable and a function to check whether it's running test:
private AtomicBoolean isRunningTest;
public synchronized boolean isRunningTest () {
if (null == isRunningTest) {
boolean istest;
try {
Class.forName ("myApp.package.name.test.class.name");
istest = true;
} catch (ClassNotFoundException e) {
istest = false;
}
isRunningTest = new AtomicBoolean (istest);
}
return isRunningTest.get ();
}
This avoids doing the try-catch check every time you need to check the value and it only runs the check the first time you call this function.
How about a flag in BuildConfig class?
android {
defaultConfig {
// No automatic import :(
buildConfigField "java.util.concurrent.atomic.AtomicBoolean", "IS_TESTING", "new java.util.concurrent.atomic.AtomicBoolean(false)"
}
}
Add this somewhere in your test classes.
static {
BuildConfig.IS_TESTING.set(true);
}
Building on the answers above the following Kotlin code is equivalent:
val isRunningTest : Boolean by lazy {
try {
Class.forName("android.support.test.espresso.Espresso")
true
} catch (e: ClassNotFoundException) {
false
}
}
You can then check the value of the property:
if (isRunningTest) {
// Espresso only code
}
i prefer not to use reflection which is slow on android. Most of us have dagger2 set up for dependency injection. I have a test component set up for testing. Here is a brief way you can get the application mode (testing or normal):
create a enum:
public enum ApplicationMode {
NORMAL,TESTING;
}
and a normal AppModule:
#Module
public class AppModule {
#Provides
public ApplicationMode provideApplicationMode(){
return ApplicationMode.NORMAL;
}
}
create a test runner like me:
public class PomeloTestRunner extends AndroidJUnitRunner {
#Override
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return super.newApplication(cl, MyTestApplication.class.getName(), context);
}
}
dont forget to declare it in gradle like this:
defaultConfig {
testInstrumentationRunner "com.mobile.pomelo.base.PomeloTestRunner"
}
Now create a subclass of the AppModule with override method that looks exactly like this and do not mark it as a module above the class definition :
public class TestAppModule extends AppModule{
public TestAppModule(Application application) {
super(application);
}
#Override
public ApplicationMode provideApplicationMode(){
return ApplicationMode.TESTING; //notice we are testing here
}
}
now in your MyTestApplication class that you declared in custom test runner have the following declared:
public class PomeloTestApplication extends PomeloApplication {
#Singleton
#Component(modules = {AppModule.class})
public interface TestAppComponent extends AppComponent {
}
#Override
protected AppComponent initDagger(Application application) {
return DaggerPomeloTestApplication_TestAppComponent.builder()
.appModule(new TestAppModule(application)) //notice we pass in our Test appModule here that we subclassed which has a ApplicationMode set to testing
.build();
}
}
Now to use it simply inject it in production code wherever like this:
#Inject
ApplicationMode appMode;
so when your running espresso tests it will be testing enum but when in production code it will be normal enum.
ps not necessary but if you need to see how my production dagger builds the graph its like this and declared in application subclass:
protected AppComponent initDagger(Application application) {
return DaggerAppComponent.builder()
.appModule(new AppModule(application))
.build();
}
If you are using JitPack with kotlin. You need to change Espresso's package name .
val isRunningTest : Boolean by lazy {
try {
Class.forName("androidx.test.espresso.Espresso")
true
} catch (e: ClassNotFoundException) {
false
}
}
For checking
if (isRunningTest) {
// Espresso only code
}
I'll create two files like below
src/main/.../Injection.java
src/androidTest/.../Injection.java
And in Injection.java I'll use different implementation, or just a static variable int it.
Since androidTest is the source set, not a part of build type, I think what you want to do is hard.
You can use SharedPreferences for this.
Set debug mode:
boolean isDebug = true;
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("DEBUG_MODE", isDebug);
editor.commit();
Check if debug mode:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
boolean isDebug = sharedPref.getBoolean("DEBUG_MODE", false);
if(isDebug){
//Activate debug features
}else{
//Disable debug features
}
Here is a way to adapt the accepted solution for a react-native Android App.
// MainActivity.java
// ...
#Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
// ...
#Override
protected Bundle getLaunchOptions() {
Bundle initialProperties = new Bundle();
boolean testingInProgress;
try {
Class.forName ("androidx.test.espresso.Espresso");
testingInProgress = true;
} catch (ClassNotFoundException e) {
testingInProgress = false;
}
initialProperties.putBoolean("testingInProgress", testingInProgress);
return initialProperties;
}
};
}
}
You will then be able to access testingInProgress as a prop given to your top-most component (typically App.js). From there you can use componentDidMount or equivalent to access it and throw it into your Redux store (or whatever you are using) in order to make it accessible to the rest of your app.
We use this to trigger some logic in our app to assist us taking screenshots with fastlane.
I would suggest using a boolean variable initialized to false in another class called, for instance, Settings.java:
private static boolean isRunningAndroidTest = false;
This boolean variable would have following setter and getter also defined in Settings.java:
public static void setIsRunningAndroidTest(boolean isRunningAndroidTest) {
Settings.isRunningAndroidTest = isRunningAndroidTest;
}
public static boolean getIsRunningAndroidTest() {
return isRunningAndroidTest;
}
One could then toggle this isRunningAndroidTest variable to true at the beginning of the androidTest file by calling the setter defined in Settings.java as follows:
Settings.setIsRunningAndroidTest(true);
Finally, the actual value of this boolean variable can later be checked in any other files by calling its corresponding getter defined in Settings.java as follows:
if (Settings.getIsRunningAndroidTest()) {
// Do something in case an androidTest is currently running
} else {
// Do something else in case NO androidTest is currently running
}

Categories

Resources