Robolectric Unit Test Sample Code for Android

In your project gradle file, change the classpath dependencies to the following.

dependencies {
    classpath 'com.android.tools.build:gradle:1.2.3'
}

In your app gradle file, add junit and roblectric dependencies. The android skd version should be 21 since Robolectric is not supporting newer versions of Android yet.

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile "com.android.support:appcompat-v7:21.0.+"
    testCompile 'junit:junit:4.12'
    testCompile "org.robolectric:robolectric:3.0-rc3"
}

Make sure junit works by create a basic junit test without the Adnroid framework. This file should be in app/src/test/java. You need to switch to project perspective in the directory navation widow in order to see this direction. All the Robolectric unit tests will be created in this folder going forward. To run this, make sure you select the Build Variants from the left sidebar and pick Unit Test, then right click the test file and select run.

import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class JUnitTest {
    @Test
    public void checkJUnitWork() {
        // We fail this unit test on purpose
        assertThat(true, is(false));
    }
}

Before create Robolectric test Android tests, let’s create a custom Roobolectric Runner. This should be in the unit test folder.

import org.junit.runners.model.InitializationError;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.res.FileFsFile;
import org.robolectric.res.FsFile;

import org.junit.runners.model.InitializationError;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

public class CustomRobolectricRunner extends RobolectricTestRunner {

    public CustomRobolectricRunner(Class<?> testClass)
            throws InitializationError {
        super(testClass);
        String buildVariant = (BuildConfig.FLAVOR.isEmpty()
                ? "" : BuildConfig.FLAVOR+ "/") + BuildConfig.BUILD_TYPE;
        String intermediatesPath = BuildConfig.class.getResource("")
                .toString().replace("file:", "");
        intermediatesPath = intermediatesPath
                .substring(0, intermediatesPath.indexOf("/classes"));

        System.setProperty("android.package",
                BuildConfig.APPLICATION_ID);
        System.setProperty("android.manifest",
                intermediatesPath + "/manifests/full/"
                        + buildVariant + "/AndroidManifest.xml");
        System.setProperty("android.resources",
                intermediatesPath + "/res/" + buildVariant);
        System.setProperty("android.assets",
                intermediatesPath + "/assets/" + buildVariant);
    }
}

Let’s test the activity title of the MainActivity class. Create the class RobolectricTestMainActivity and run it by right click the file and select run. This test will fail. To pass it, just change the string “Fail this test on purpose” to the correct title you have set for your activity.

import android.app.Activity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

@RunWith(CustomRobolectricRunner.class)
public class RobolectricTestMainActivity {
    @Test
    public void titleIsCorrect() throws Exception {
        Activity activity = Robolectric.setupActivity(MainActivity.class);
        assertThat("Should be Unit Test", activity.getTitle().toString(), equalTo("Fail this test on purpose"));
    }
}

At this point, everything should have set up for unit test using Robolectric. For more Robolectric unit test samples, keep on reading the following:
RobolectricTestTextView.java for testing TextView

import android.app.Activity;
import android.widget.TextView;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

@RunWith(CustomRobolectricRunner.class)
public class RobolectricTestTextView {

    Activity activity;

    @Before
    public void init() {
        activity = Robolectric.setupActivity(MainActivity.class);
    }

    @Test
    public void failTest() {
        TextView results = (TextView) activity.findViewById(R.id.hello);
        String resultsText = results.getText().toString();
        assertThat(resultsText, equalTo("Testing Android Rocks!"));
    }

    @Test
    public void passTest() {
        TextView results = (TextView) activity.findViewById(R.id.hello);
        String resultsText = results.getText().toString();
        assertThat(resultsText, equalTo("Hello World!"));
    }
}

RobolectricTestOptionMenu.java for testing the option menu item

import android.app.Activity;
import android.view.Menu;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowToast;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;


@RunWith(CustomRobolectricRunner.class)
public class RobolectricTestOptionMenu {
    Activity activity;

    @Before
    public void init() {
        activity = Robolectric.setupActivity(MainActivity.class);
    }

    @Test
    public void onCreate_shouldInflateLayout() throws Exception {
        final Menu menu = Shadows.shadowOf(activity).getOptionsMenu();
        assertThat(menu.findItem(R.id.item1).getTitle().toString(), equalTo("item 1"));
        assertThat(menu.findItem(R.id.item2).getTitle().toString(), equalTo("item 2"));
    }

    @Test
    public void clickMenuItem_shouldDelegateClickToFragment() {
        Shadows.shadowOf(activity).clickMenuItem(R.id.item4);
        assertThat(ShadowToast.getTextOfLatestToast(), equalTo("Clicked Item 4"));
    }
}

RobolectricTestButton.java for testing button and button click.

import android.app.Activity;
import android.content.Intent;
import android.widget.Button;
import android.widget.TextView;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowToast;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.*;

@RunWith(CustomRobolectricRunner.class)
public class RobolectricTestButton {
    Activity activity;

    @Before
    public void init() {
        activity = Robolectric.setupActivity(MainActivity.class);
    }

    @Test
    public void clickingButton_shouldChangeResultsViewText() throws Exception {
        Button button = (Button) activity.findViewById(R.id.button);
        button.performClick();
        Intent intent = Shadows.shadowOf(activity).peekNextStartedActivity();
        assertEquals(SecondActivity.class.getCanonicalName(), intent.getComponent().getClassName());
    }

    @Test
    public void testButtonClick() throws Exception {
        Button view = (Button) activity.findViewById(R.id.button);
        assertNotNull(view);
        view.performClick();
        assertThat(ShadowToast.getTextOfLatestToast(), equalTo("Hello"));
    }
}

RobolectricTestIntentService.java for testing intent service.

import android.content.Context;
import android.content.Intent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.fakes.RoboSharedPreferences;
import static org.junit.Assert.assertNotSame;

@RunWith(CustomRobolectricRunner.class)
@Config(constants = BuildConfig.class)
public class RobolectricTestIntentService {

    @Test
    public void addsDataToSharedPreference(){
        RoboSharedPreferences preferences = (RoboSharedPreferences) RuntimeEnvironment.application
                .getSharedPreferences("example", Context.MODE_PRIVATE);
        Intent intent =  new Intent(RuntimeEnvironment.application,SampleIntentService.class);
        SampleIntentService registrationService = new SampleIntentService();

        registrationService.onHandleIntent(intent);

        assertNotSame(preferences.getString("SAMPLE_DATA", ""), "");
    }
}

RobolectricTestAlarmManagerReceiver.java for testing AlarmManagerReceiver

import android.app.Application;
import android.content.Intent;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.robolectric.Shadows.shadowOf;

@RunWith(CustomRobolectricRunner.class)
@Config(constants = BuildConfig.class)
public class RobolectricTestAlarmManagerReceiver {

    @Test
    public void startServiceForTheScheduledAlarm(){
        Application application = RuntimeEnvironment.application;
        Intent expectedService = new Intent(application, SampleIntentService.class);

        AlarmManagerReceiver alarmManagerReceiver = new AlarmManagerReceiver();
        alarmManagerReceiver.onReceive(application, new Intent());

        Intent serviceIntent = shadowOf(application).getNextStartedService();
        assertNotNull(serviceIntent);
        assertEquals(serviceIntent.getComponent(),
                expectedService.getComponent());
    }
}

To satisfy the above Robolectric unit test cases, create the following Android Application layout files and class files.
activity_main.xml in the res/layout/ folder

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="To Second Activity"
        android:onClick="toSecondActivity"/>
</RelativeLayout>

fragment_main.xml in the res/layout/ folder

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Fragment Main"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

activity_main.xml in the res/menu/ folder, create the the menu folder if it’s not yet there.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:robolectric="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/item1"
    android:title="item 1"
    robolectric:showAsAction="ifRoom"/>
<item android:id="@+id/item2"
    android:title="item 2"
    robolectric:showAsAction="never"/>
</menu>

fragment_main.xml in the res/menu/ folder.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:robolectric="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/item3"
        android:title="item 3"
        robolectric:showAsAction="never"/>
    <item android:id="@+id/item4"
        android:title="item 4"
        robolectric:showAsAction="never"/>
</menu>

MainActivity.java

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item1:
                Toast.makeText(this, "Clicked Item 1", Toast.LENGTH_SHORT).show();
                return true;

            case R.id.item2:
                Toast.makeText(this, "Clicked Item 2", Toast.LENGTH_SHORT).show();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public void toSecondActivity(View v) {
        Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show();
        Intent i = new Intent(this, SecondActivity.class);
        startActivity(i);
    }

}

SecondActivity.java

import android.app.Activity;
import android.os.Bundle;

public class SecondActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

MainFragment

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class MainFragment extends Fragment {

    public static Fragment newInstance() {
        return new MainFragment();
    }

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle bundle) {
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item3:
                Toast.makeText(getActivity(), "Clicked Item 3", Toast.LENGTH_SHORT).show();
                return true;

            case R.id.item4:
                Toast.makeText(getActivity(), "Clicked Item 4", Toast.LENGTH_SHORT).show();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

SampleIntentService.java

import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;

public class SampleIntentService extends IntentService {
    public SampleIntentService() {
        super("SampleIntentService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences(
                "example", Context.MODE_PRIVATE).edit();
        editor.putString("SAMPLE_DATA","sample data");
        editor.apply();
    }
}

AlarmManagerReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AlarmManagerReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent intentService = new Intent(context, SampleIntentService.class);
        context.startService(intentService);
    }
}

Complete example in Github
References:
https://github.com/robolectric/robolectric-samples
http://nenick-android.blogspot.com/2015/03/android-studio-110-and-robolectric-30.html

Search within Codexpedia

Custom Search

Search the entire web

Custom Search