Library resources with Robolectric 3 - JodaTime - android

Getting an ResourceNotFoundException when using a library with Robolectic 3.0-rc3. The resource is declared in build.gradle with compile 'net.danlew:android.joda:2.8.0'. Specifically this is the Android port of Joda-Time.
android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f0501da
at org.robolectric.shadows.ShadowResources.checkResName(ShadowResources.java:343)
at org.robolectric.shadows.ShadowResources.getResName(ShadowResources.java:333)
at org.robolectric.shadows.ShadowResources.openRawResource(ShadowResources.java:382)
at android.content.res.Resources.openRawResource(Resources.java)
at net.danlew.android.joda.ResourceZoneInfoProvider.openResource(ResourceZoneInfoProvider.java:120)
at net.danlew.android.joda.ResourceZoneInfoProvider.<init>(ResourceZoneInfoProvider.java:39)
Application class:
#Override
public void onCreate() {
super.onCreate();
JodaTime.init(this);
}
My test class:
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class,
sdk = 21)
public class MyTest {
#Before
public void setup() {
}
#Test
public void myTest() {
//Test my stuff
}
}

You need to initialise the library in your tests, with the Robolectric runtime environment. So add this to your setup() methods.
JodaTimeAndroid.init(RuntimeEnvironment.application);
So your test would look something like this:
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
public class MyApplicationTest {
#Before
public void setup() {
JodaTimeAndroid.init(RuntimeEnvironment.application);
}
#Test
public void myTest() {
//Test my stuff
DateTime aDateTime = new DateTime();
DateTime bDateTime = new DateTime(aDateTime);
assertEquals(aDateTime, bDateTime);
}
}

Related

Espresso start activity before #BeforeClass

#Before class does not start the activity. For this reason, no views to do actions on are available. Is it possible to have the activity started before #BeforeClass
An exemplary test that fails due to this:
#RunWith(AndroidJUnit4.class)
public class MakeFeedingTest {
#Rule
public ActivityScenarioRule<MainActivity> scenarioRule = new ActivityScenarioRule<>(MainActivity.class);
#BeforeClass
public static void setup() {
onView(withId(R.id.add)).perform(click());
onView(withId(R.id.save)).perform(click());
}
#Test
public void superBasicTest() {
onView(withId(R.id.new_element)).check(matches(isDisplayed()));
}
}
How can I make the activity start before #BeforeClass is executed, so that the test does not fail anymore?
Usecase: Add an element to a list before the other tests are exectued.
That is not relevant design pattern here, and I wouldnt do it in that way.
For this to work, do something like this:
#RunWith(AndroidJUnit4.class)
public class MakeFeedingTest {
#Rule
public ActivityScenarioRule<MainActivity> scenarioRule = new ActivityScenarioRule<>(MainActivity.class);
#BeforeClass
public static void setup() {
}
#Test
public void superBasicTest() {
clickButtons()
onView(withId(R.id.new_element)).check(matches(isDisplayed()));
}
private void clickButtons() {
onView(withId(R.id.add)).perform(click());
onView(withId(R.id.save)).perform(click());
}
}
If you're insisting on using it in this way, add aditional parameters to the screnario rule as following and see if that will work:
#Rule
public ActivityScenarioRule<MainActivity> scenarioRule = ActivityTestRule(MainActivity.class.java, true, true)

android unit test + robolectric 3.0 + java.lang.LinkageError: loader constraint violation

Error:
java.lang.LinkageError: loader constraint violation: when resolving
method "com.example.demo.utils.R.init(Landroid/content/Context;)V" the
class loader (instance of
org/robolectric/internal/bytecode/InstrumentingClassLoader) of the
current class, com/example/test/FirstTest, and the class loader
(instance of sun/misc/Launcher$AppClassLoader) for the method's
defining class, com/example/demo/utils/R, have different Class objects
for the type android/content/Context used in the signature
test code:
#runwith(RobolectricGradleTestRunner.class)
#config(constants = BuildConfig.class,sdk = 21,application = TestApplication.class)
public class FirstTest{
#test
public void testCase01(){
MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);
....
}
}
build.gradle:
dependencies {
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.0"
testCompile 'org.robolectric:shadows-httpclient:3.0'
...
}
src/test/java/.../TestApplication:
public class TestApplication extends Application {
}
com/example/demo/MainActivity:
public class MainActivity extends Activity {
#override
protected void onCreate(Bundle savedInstanceState) {
...
com.example.demo.utils.R.init(getApplicationContext());
...
}
}
com/example/demo/utils/R:
public final class R {
public static Resources resources;
private static String packageName;
public static void init(Context paramContext) {
resources = paramContext.getResources();
packageName = paramContext.getPackageName();
}
...
}
I find the reason why tests run fail is using a class named com.example.demo.utils.R, which has a conflict with an R class
autogenerated by the Android System. If you rename R to another name, like Ra, it works.

Mocking dependency error with AndroidJunitRunner and Dagger2

I am trying to mock dependencies like what is suggested in https://artemzin.com/blog/how-to-mock-dependencies-in-unit-integration-and-functional-tests-dagger-robolectric-instrumentation/
Unfortunately I can't get past the following error when I run my AndroidJunit4 test :
Test running failed: Unable to find instrumentation info for: ComponentInfo{com.fisincorporated.aviationweather.test/android.support.test.runner.AndroidJUnitRunner}
I tried various SO solutions that were not Android Studio version dependent with no luck
My app level gradle code snippet is:
android {
...
defaultConfig {
...
testInstrumentationRunner "com.fisincorporated.aviationweather.app.OverrideApplicationTestRunner"
}
...
}
My OverrideApplicationTestRunner is:
public class OverrideApplicationTestRunner extends AndroidJUnitRunner {
#Override
#NonNull
public Application newApplication(#NonNull ClassLoader cl,
#NonNull String className,
#NonNull Context context)
throws InstantiationException,
IllegalAccessException,
ClassNotFoundException {
return Instrumentation.newApplication(WeatherApplicationTest.class, context);
}
}
WeatherApplicationTest
public class WeatherApplicationTest extends WeatherApplication {
#Override
protected void createDaggerInjections() {
component = DaggerDiComponent.builder()
.appModule(new AppModule(this) {
#Override
public String providesAppSharedPreferencesName() {
return "SHARED_AIRPORT_FUNCTIONAL_TEST";
}
public Retrofit provideAppRetrofit() {
return new AppRetrofit(new MockInterceptor()).getRetrofit();
}
})
.build();
component.inject(this);
}
}
And AirportWeatherActivityTest
#RunWith(AndroidJUnit4.class)
public class AirportWeatherActivityTest {
#Rule
public ActivityTestRule<AirportWeatherActivity> mActivityRule =
new ActivityTestRule<>(AirportWeatherActivity.class, true, false);
#Test
public void someTest() {
Context targetContext = InstrumentationRegistry.getTargetContext();
Intent intent = new Intent(targetContext, AirportWeatherActivity.class);
mActivityRule.launchActivity(intent);
assertThat(mActivityRule.getActivity().airportWeatherViewModel.airportWeatherList.size(),is(0));
}
}
androidTest directory structure is below:
I have found that if I run the following test, it works, i.e. I see that WeatherApplicationTest is being executed. So it would seem that testInstrumentationRunner is finding my OverrideApplicationTestRunner.
#RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
#Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.fisincorporated.aviationweather", appContext.getPackageName());
}
}
So is problem caused by using an ActivityTestRule?
P.S. I neglected to say I am a newbie on testing so my apologizes if I am missing something obvious.
Switching android plugin version to 2.2.3 and then back to 2.3.0 back, cleaning project and building fixes the issue.

Instrumental unit testing of activity with FirebaseAuth

I'm trying to setup and instrumental unit test for Activity with FirebaseAuth. When I run the application, everything works just fine. The problem is within the setup of instrumental unit tests.
Activity:
public final class GoogleSignInActivity extends AppCompatActivity{
#Override
protected void onCreate(final Bundle savedInstanceState) {
...
if (FirebaseApp.getApps(this).isEmpty()) {
FirebaseApp.initializeApp(this);
}
mFirebaseAuth = FirebaseAuth.getInstance();
}
}
Test:
#RunWith(AndroidJUnit4.class)
public class GoogleSignInActivityIntegrationTest extends UiTestPrerequesites {
#Rule
public final ActivityTestRule<GoogleSignInActivity> mActivityRule = new ActivityTestRule<>(
GoogleSignInActivity.class, false, true);
#Before
public void setup(){
if (FirebaseApp.getApps(InstrumentationRegistry.getContext()).isEmpty()) {
FirebaseApp.initializeApp(InstrumentationRegistry.getContext());
}
}
#Test
#SmallTest
public void implements_GoogleSignInWorkerFragment_GoogleSignInUiChangesListener() {
//FirebaseApp.initializeApp(InstrumentationRegistry.getContext()); (this doesn't help)
assertThat(mActivityRule .getActivity(),
notNullValue());
}
}
Exception (only when running test, not app):
Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.twofortyfouram.ui.test. Make sure to call FirebaseApp.initializeApp(Context) first.
I think your issue with applicationID ( a.k.a package name ). you should add your application Id for testing to Firebase project account as well.
it has suffix: test
In general it looks like:
[ApplicationID].test
i.e.
com.apipas.android.hello.test
release applicationId is
com.apipas.android.hello
I hope that may help you,'.

Robolectric ShadowActivity error

I am starting to get familiar with Robolectric to create unit tests for Android applications.
My initial test:
#RunWith(RobolectricTestRunner.class)
public class MainActivityTest {
private MainActivity mainActivity;
#Before
public void setUp() throws Exception {
mainActivity = Robolectric.buildActivity(MainActivity.class).create().get();
mainActivity.onCreate(null);
}
#Test
public void sample() throws Exception {
ShadowActivity act = Robolectric.shadowOf(mainActivity);
}
}
But Robolectric.shadowOf(mainActivity) gives me an error:
The type android.animation.Animator cannot be resolved. It is indirectly referenced from required .class files
Any ideas why? I have created simple android app with Android API Level 8. For the tests, I have Robolectric 2.1 jar
changet from shadowOf(mainActivity) to shadowOf_(mainActivity) and everything works fine!

Categories

Resources