We are happy to invite you to the Speakers’ Corner today, on Thursday May 29, from 18.30 till 19.30 at SkyPoint to meet Thomas Vervik, Head of Development Bipper Communications who will talk on “How to save money on QA - Dependency Injection and automated testing on Android”
Thomas is Head of Development for Bipper Communications, and has been managing the company's team in Kiev since February 2012. Originally a seasoned Java server backend/frontend developer, he has the last two years started mobile development, first with HTML 5 and later Android.
Mobile development has since its birth around 2008 gone from simple apps to more complex enterprise similar software. The increase in size and complexity yields the need for structuring the code differently in order to handle the new complexity. The tools used to handle this complexity has been applied to server side development for years, but mobile development has been lagging behind.
But not anymore. New frameworks built on proven paradigms are emerging, and in this Speakers Corner we will introduce Dependency Injection for Android, the motivation for its use, and one of the implementations - Dagger. Dependency Injection has several advantages, but in this presentation we will focus on how it enables to write proper automated tests.
9. Dependency Carrying
class MyActivity extends Activity {
onClick(View v) {
A a = new A(this);
a.doSometing();
}
}
class A {
Context mContext;
public (Context mContext){
this.mContext = mContext;
}
public doSomething() {
B b = new B(mContext);
String str =
b.getSomeString(R.strings.helloWorld);
}
}
class B {
Context mContext;
public B(Context mContext) {
this.mContext = mContext;
}
public String getSomeString(int resourceId) {
return
mContext.getString(resourceId);
}
}
10. Reduced Dependency Carrying
@Module class ProdModule {
Context mContext;
public ProdModule(Context mContext) {
this.mContext = mContext;
}
@Provide B provideB() {
return new B(context);
}
@Provide A provideA(B b) {
return new A(b);
}
}
class MyActivity {
@Inject A a;
onCreate(){
((MyApplication)getApplication()).inject(this);
}
onClick(View v) {
A a = new A(this);
a.doSomething();
}
}
class A {
@Inject B b;
public doSomething() {
String str = b.getSomeString(R.strings.helloWorld);
}
}
class B {
Context mContext;
public B(Context mContext) {
this.mContext = mContext;
}
public String getSomeString(int resourceId) {
return mContext.getString(resourceId);
}
}
21. Lazy<T>
class GridingCoffeeMaker {
@Inject Lazy<Grinder> lazyGrinder;
public void brew() {
while (needsGrinding()) {
// Grinder created once and cached.
Grinder grinder = lazyGrinder.get()
grinder.grind();
}
} }
24. Live coding - Sample 1
● add dependencies (with Gradle)
● create module
● set up Dagger in Application context
● inject dependencies to Activity
● create Activity test which injects a mock
29. Inject dependencies Activity
class MainActivity extends Activity {
@Inject
MyStringUtils myStringUtils;
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set dependencies to this activity
((MyApplication)getApplication()).inject(this);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(this);
}
30. Unit test Activity with mock
class MainActivityUnitTest extends ActivityUnitTestCase<MainActivity> {
@Inject
MyStringUtils myStringUtils;
void setUp() {
// create test application context, Dagger Graph with our test module.
MyApplication application = new TestApplication();
application.inject(this); // inject the dependencies we need to this class
setApplication(application); // use our custom test application context
}
void testOnClick() {
String testingStr = "olala";
when(myStringUtils.helloWorld()).thenReturn(testingStr);
this.activity = startActivity(intent, null, null);
// the test
View view = activity.findViewById(R.id.button);
activity.onClick(view);
// verify the mock was invoked
verify(myStringUtils, times(1)).helloWorld();
// assert view got updated correctly
TextView msgView = (TextView) activity.findViewById(R.id.textView);
assertEquals(testingStr, msgView.getText());
}
33. Tips, tricks and Frameworks
● https://github.com/tha022/dagger-testing-example
● https://github.com/fizz-buzz/fb-android-dagger
Hinweis der Redaktion
So we gonna build a sample app which shows:
1) how to set up the object graph in Application context.
2) how inject dependencies into an Activity
3) when clicking button, spin off a background thread which makes an HTTP request and show the request in view
4) build test module which mocks the HTTP client
5) create ActivityUnitTest which loads the Test module and injects the HTTP client