android - How do I make my activity use testing data? -


i have application displays data (posts) web api.

  • a background service syncs data @ unknown time , saves it.
  • when visiting main activity loads data , displays in recyclerview
  • the loading handled via singleton class

i test main activity follows

@rule public activitytestrule<mainactivity> mactivityrule = new activitytestrule<>(mainactivity.class);  @test public void testdataload() {     int poststotal = datasingleton.getinstance().getpostscount();     viewinteraction empty = onview(withid(r.id.empty_view));     viewinteraction recycler = onview(withid(r.id.recycler_view));     if (poststotal == 0) {         empty.check(matches(isdisplayed()));         recycler.check(matches(not(isdisplayed())));     } else {         empty.check(matches(not(isdisplayed())));         recycler.check(matches(isdisplayed()));         recycler.check(new recyclerviewitemcountassertion(greaterthan(poststotal)));     } } 

i know can't right way write tests. want able test both empty data set , non-empty set if-else 2 separate tests. way think can achieve mock data.

is there way? can use mockito make mainactivity use mock data without modifying production code? choice make inject either real or mocked data providers in place of singleton?

is better uninstall , reinstall app each time there no data start , continue real data testing?

android activity heavyweight , hard test. because don't have control on constructor, hard swap in test doubles.

the first thing make sure depending on abstraction of data-source rather concretion. if using singleton getpostscount() method extract interface:

interface datasourceabstraction {     int getpostscount(); } 

make wrapper class implements interface:

class concretedatasource implements datasourceabstraction {     @override     int getpostscount() {         return datasingleton.getinstance().getpostscount();     } } 

and make activity depend on rather concrete datasingleton

datasourceabstraction datasourceabstraction;  @override protected void oncreate(bundle savedinstancestate) {     super(savedinstancestate);     injectmembers(); }  @visiblefortesting void injectmembers() {     datasourceabstraction = new concretedatasource(); } 

you can swap in test double subclassing , overriding injectmembers has relaxed visibility. it's bad idea in enterprise development, there less options in android activities don't control constructor of class.

you can write:

datasourceabstraction datasource;  //system under test mainactivity mainactivity  @before public void setup() {     mockdatasource = mockito.mock(datasourceabstraction.class);     mainactivity = new mainactivity() {         @override         void injectmembers() {             datasourceabstraction = mockdatasource;         }     }; } 

Comments

Popular posts from this blog

cookies - Yii2 Advanced - Share session between frontend and mainsite (duplicate of frontend for www) -

angular - password and confirm password field validation angular2 reactive forms -

php - Permission denied. Laravel linux server -