Testing Android UI with Mock API Responses

Read Time 2 minutes

Most of the times our android apps load data from a backend server. Testing such an android app is difficult, as test depends on the network and external backend server. Any issue with the network connection or our server will cause our tests to fail.

When testing UI, all we need to test is whether data is being displayed properly or not and whether performing a particular action leads to expected result or not. So we don’t really need to depend and wait for our Async API calls to finish.

In this article I am going to explain how we can provide static JSON responses for UI testing using Dagger modules. Dagger is DI framework used to provide application wide dependencies. You can read more about Dagger in my previous article Be More Productive with Dagger2 .

In my sample application I am using Dagger for providing different dependencies like HttpClient, Retrofit and Repository. These Dagger modules provide real dependencies. In order to provide mock JSON responses, we need to create another Dagger module which will provide mock dependencies when running UI tests.

Let’s get started without further delay. This is my Application Module providing the BreedRespository  dependency.

@Module
public class ApplicationModule {

    @Provides
    @Singleton
    public BreedRepository provideBreedRepository(BreedRepositoryImpl repository) {
        return repository;
    }

}

and here is the BreedRespository.java

public interface BreedRepository {
    Observable<List<Breed>> getBreedList();
}

Actual implementation calls REST API to get breed list using retrofit. We inject these dependencies in our application class.

public class MyApplication extends Application {

    private ApplicationComponent applicationComponent;

    @Override
    public void onCreate() {
        super.onCreate();
       initializeInjector();
    }


    private void initializeInjector() {
        applicationComponent =
                DaggerApplicationComponent.builder()
                        .applicationModule(new ApplicationModule(this))
                        .networkModule(new NetworkModule())
                        .databaseModule(new DatabaseModule())
                        .build();
    }

    public ApplicationComponent getApplicationComponent() {
        return applicationComponent;
    }
}

 

In order to inject MockApplicationModule we first need to create and specify a TestApplication class which will injects the mock module while running UI tests. Let’s create a TestApplication class to inject mock module.

public class TestApplication extends MyApplication {

    @Override
    public ApplicationComponent getApplicationComponent() {
        return DaggerApplicationComponent.builder()
                .applicationModule(new MockAppModule(this))
                .databaseModule(new DatabaseModule())
                .networkModule(new NetworkModule())
                .build();
    }

    //mock module
    private class MockAppModule extends ApplicationModule {

        public MockAppModule(Context context) {
            super(context);
        }

        @Override
        public BreedRepository provideBreedRepository(BreedRepositoryImpl repository) {
            return new BreedRepository() {
                @Override
                public Observable<List<Breed>> getBreedList() {
                    Gson gson = new Gson();
                    Type listType = new TypeToken<List<String>>() {
                    }.getType();
                    List<String> breedList = gson.fromJson(JsonUtils.breedListJson, listType);

                    BreedMapper breedMapper = new BreedMapper();


                    return Observable.just(breedMapper.map(breedList));
                }
            };
        }
}

 

If you notice we are providing MockAppModule while building the DaggerApplicationComponent in our TestApplication and we are simply returning static JSON in getBreedList(). Static JSON for getBreedList is defined in JsonUtils:

public class JsonUtils {

    public static final String breedListJson = "[\"affenpinscher\"," +
            "\"african\"" +
            ",\"airedale\"" +
            ",\"akita\"," +
            "\"appenzeller\"]";
}

 

Now our MockApplication is ready. All we need is to configure our TestRunner to use this  . Let’s create our custom test runner.

public class MockTestRunner extends AndroidJUnitRunner {

    @Override
    public void onCreate(Bundle arguments) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());

        super.onCreate(arguments);
    }

    @Override
    public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return super.newApplication(cl, TestApplication.class.getCanonicalName(), context);
    }
}

Make sure, you create both the TestApplicaiton.java and MockTestRunner in androidTest package.

One last step is to change our app build.gradle so that it uses our MockTestRunner for running  UI tests.

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "aziz.sohail.mvpsample"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "aziz.sohail.mvpsample.MockTestRunner"


    }

 

Now when you run UI tests in androidTest package, mock response will be received instead of real API. Happy coding 🙂

You can find the complete source code here.

 

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *