[Android] Setting a quick instrumentation test environment with Espresso + JUnit + Mockito

1.- Gradle dependencies – global build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
} 

2.- Gradle dependencies – app/build.gradle

defaultConfig {
    applicationId "..."
    minSdkVersion 15
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}

dependencies { 
    // ... testCompile 'junit:junit:4.12' 
    androidTestCompile 'com.google.dexmaker:dexmaker:1.2' 
    androidTestCompile('com.google.dexmaker:dexmaker-mockito:1.2') { 
        exclude group: 'org.hamcrest', module: 'hamcrest-core' 
    }
    androidTestCompile 'com.android.support.test:runner:0.4.1' 
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'org.mockito:mockito-core:1.10.19' 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.1') 
    { 
        exclude group: 'javax.inject', module: 'javax.inject'
        exclude group: 'com.squareup', module: 'javawriter' 
    }
    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') 
    { 
        exclude module: 'support-annotations' 
        exclude module: 'recyclerview-v7' exclude module: 'support-v4' 
    }
    androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.1') 
    testCompile "org.mockito:mockito-core:1.9.5" 
    testCompile 'org.mockito:mockito-all:1.9.5' 
}

configurations.all { 
    resolutionStrategy.force 'com.android.support:support-annotations:23.0.1' 
}

3.- Sample test (androidTest/com/package/name folder)

@RunWith(AndroidJUnit4.class) @LargeTest
public class IssuesActivityTest {
    @Rule
    public IntentsTestRule<IssuesActivity> activityRule =
            new IntentsTestRule<>(IssuesActivity.class, true, false);

    @Test
    public void shouldDisplayToolbarOnStart() {
        startActivity();

        onView(withId(R.id.toolbar)).check(matches(isDisplayed()));
    }

    private IssuesActivity startActivity() {
        return activityRule.launchActivity(null);
    }
}

And that’s all folks

Advertisements

[Android] Sugar ORM is not creating tables on DB creation/migration

I was having this issue in two scenarios:

– Database creation from zero (app just installed)
– Database migration (for example from v2 to v3)

there were two tables that weren’t being created.

I discovered that they both had only one constructor, with parameters.
After adding an empty constructor, both tables were created.

public NotificationDBEntry() {
}

public ProjectDBEntry() {
}

So there are two choices to make it work:
– In classes with no constructor, it will work because the default one is the empty constructor
– In classes with a non-empty constructor, it is mandatory to add an empty constructor.

Hope this saves you time!

[Android] Configuring a quick test environment

In order to start writing tests for our app, one quick solution could be this one:

1.- Adding junit to our build.gradle file

dependencies{
...
testCompile 'junit:junit:4.12'
}

2.- Creating the test folder structure
This can be done with Android Studio, or directly in your file explorer (finder, nautilus, etc). Create the folder

your_app_folder/app/src/test/java/com/companyname/appname/

where the app’s package name would be com.companyname.appname (substitute by yours).

3.- Creating a sample test
Inside the recently created folder, create a file named ProjectTest.java and copy this content:

public class ProjectTest {
@Test
public void shouldCompare1To1() throws Exception {
assertEquals(1, 1);
}
}

4.- Running the tests in console
Go to terminal, move to your app’s folder and do

./gradlew test

If everything went fine, you should have a single test passing

[Android] Getting RAW JSON response with Retrofit2

The main thing that made me waste time when using Retrofit was that I could not see the JSON responses that my APIs were sending. I had to add a separate method to the RetrofitService that used a Response object instead of MyClass object.
This is much easier and comfortable in retrofit 2. Just add these lines:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LogJsonInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();

LogJsonInterceptor class:


public class LogJsonInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();

Response response = chain.proceed(request);
String rawJson = response.body().string();

Log.d(BuildConfig.APPLICATION_ID, String.format("raw JSON response is: %s", rawJson));

// Re-create the response before returning it because body can be read only once
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), rawJson)).build();
}
}

Here you can log your rawJson variable to display raw JSON message. Note that once body() has been called, the response has been consumed and becomes useless. You have to re-create it before returning it to another objects to consume.

Thanks to this article written by @riggaroo and this issue thread (and ofcourse uncle Jake) for making this possible.

Have a nice coding day !!! 🙂

P.D. I know that the article format is crap, but anyway you can copy and paste the code for your own purpose and it will work 😛

[Android] imeOptions not working on EditText (actionNext, actionDone)

Don’t forget to add

<item name=”android:inputType”>text</item>

or

<item name=”android:inputType”>textPassword</item>

to your EditText’s style

Directly on XML:

<EditText
style=”@style/PasswordEditText”
android:id=”@+id/login_et_password”
android:layout_below=”@+id/login_tv_password”
android:inputType=”text”
android:imeOptions=”actionDone”
/>

[Android SDK] Using variables from Gradle, in Java code

This is a pretty simple issue, but I’ve seen many questions and bad solutions about it.

An example of doing that could be:

file: app/build.gradle

android{
   buildTypes{
       release{
           buildConfigField "int", "SAMPLE_INT", "52"
           buildConfigField "boolean", "SAMPLE_BOOL", "true"
           buildConfigField "String", "SAMPLE_STR", "\"release_foo\""
       }
       debug{
           buildConfigField "int", "SAMPLE_INT", "55"
           buildConfigField "boolean", "SAMPLE_BOOL", "false"
           buildConfigField "String", "SAMPLE_STR", "\"debug_foo\""
       }
   }
}

file: MainActivity.java

@Override
 protected void onCreate(Bundle savedInstanceState){
     String gradleStr = BuildConfig.SAMPLE_STRING;
     int gradleInt = BuildConfig.SAMPLE_INT;
     boolean gradleBool = BuildConfig.SAMPLE_BOOL;
 }

As simple as that 🙂

hope it helps for you!