android - Mockito unit test BaseObserver and static method with context -
i facing unit testing first time , know best approach following scenario. using mockito tests. following test logic(presenter) layer , trying verify behaviors of view.
app classes
the method of presenter need include in test:
public void loadweather() { citydetailsmodel selectedcity = getdbhelper().getselectedcitymodel(); if (selectedcity != null) { getcompositedisposablehelper().execute( getapihelper().weatherapirequest(selectedcity.getlatitude(), selectedcity.getlongitude()), new weatherobserver(getmvpview())); } else { getmvpview().showemptyview(); }
}
weatherobserver:
public class weatherobserver extends baseviewsubscriber<daymvpview, weatherresponsemodel> { public weatherobserver(daymvpview view) { super(view); } @override public void onnext(weatherresponsemodel weatherresponsemodel) { super.onnext(weatherresponsemodel); if (weatherresponsemodel.getdata().isempty()) { getmvpview().showemptyview(); } else { getmvpview().showweather(weatherresponsemodel.getdata()); } } }
baseviewsubscriber (default disposableobserver base class used whenever want default error handling):
public class baseviewsubscriber<v extends basemvpview, t> extends disposableobserver<t> { private errorhandlerhelper errorhandlerhelper; private v view; public baseviewsubscriber(v view) { this.view = view; errorhandlerhelper = weatherapplication.getapplicationcomponent().errorhelper(); } public v getview() { return view; } public boolean shouldshowerror() { return true; } protected boolean shouldshowloading() { return true; } @override public void onstart() { if (!apputils.isnetworkavailable(weatherapplication.getapplicationcomponent().context())) { onerror(new internetconnectionexception()); return; } if (shouldshowloading()) { view.showloading(); } super.onstart(); } @override public void onerror(throwable e) { if (view == null) { return; } if (shouldshowloading()) { view.hideloading(); } if (shouldshowerror()) { view.onerror(errorhandlerhelper.getpropererrormessage(e)); } } @override public void oncomplete() { if (view == null) { return; } if (shouldshowloading()) { view.hideloading(); } } @override public void onnext(t t) { if (view == null) { return; } } }
compositedisposablehelper (compositedisposable helper class):
public class compositedisposablehelper { public compositedisposable disposables; public testscheduler testscheduler; @inject public compositedisposablehelper(compositedisposable disposables) { this.disposables = disposables; testscheduler = new testscheduler(); } public <t> void execute(observable<t> observable, disposableobserver<t> observer) { adddisposable(observable.subscribeon(testscheduler) .observeon(testscheduler) .subscribewith(observer)); } public void dispose() { if (!disposables.isdisposed()) { disposables.dispose(); } } public testscheduler gettestscheduler() { return testscheduler; } public void adddisposable(disposable disposable) { disposables.add(disposable); } }
my test:
@test public void loadsuccessfully() { weatherresponsemodel responsemodel = new weatherresponsemodel(); list<weathermodel> list = new arraylist<>(); list.add(new weathermodel()); responsemodel.setdata(list); citydetailsmodel citydetailsmodel = new citydetailsmodel(); citydetailsmodel.setlongitude(""); citydetailsmodel.setlatitude(""); when(dbhelper.getselectedcitymodel()).thenreturn(citydetailsmodel); when(apihelper.weatherapirequest(anystring(), anystring())).thenreturn( observable.just(responsemodel)); daypresenter.loadweather(); compositedisposablehelper.gettestscheduler().triggeractions(); verify(daymvpview).showweather(list); verify(daymvpview, never()).showemptyview(); verify(daymvpview, never()).onerror(anystring()); }
when try run test, nullpointer, because new weatherobserver(getmvpview())
called, , in baseviewsubscriber
errorhandlerhelper null because getapplicationcopomnent null. nullpointer thrown in static method apputils.isnetworkavailable()
same reason.
when try comment these lines, test ok.
my questions are:
- should use dagger unit test or? if yes please give me example test.
- should use powermockito static method
apputils.isnetworkavailable()
? if yes, ok because of method use powermockito runner
@runwith(powermockrunner.class)
?
should use dagger unit test or? if yes please give me example test.
you don't have use dagger @ test, that's dependency injection benefit you, strip dependencies out, , tests able replace them.
should use powermockito static method apputils.isnetworkavailable()? if yes, ok because of method use powermockito runner @runwith(powermockrunner.class)?
static methods bad testing, cannot replace them (at least not , without powermock) testing purposes.
better practice use dagger
production code inject dependencies, preferably @ constructor, @ tests can provide dependencies according test needs (using mocks or fakes necessary).
in case, can add both errorhandlerhelper
, apputils
baseviewsubscriber
constructor. baseviewsubscriber
shouldn't injected, need provide modules outside, in presenter, should use injection objects. again @ constructor.
@ test, replace or provide objects presenter in it's turn hand on baseviewsubscriber
.
you can read more tests seams @ android here.
besides that, odd me oo hierarchy of observer
, disposable
wraps observable getting common behavior, it's breaking functional stream oriented reactive approach, might want consider using patterns compose using transformers
, using doonxxx operators apply common behavior @ reactive streams.
Comments
Post a Comment