Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing testable Android apps

Tomáš Kypta
November 20, 2015

Writing testable Android apps

Lecture on writing testable Android apps at Socialbakers, 2015.

Tomáš Kypta

November 20, 2015
Tweet

More Decks by Tomáš Kypta

Other Decks in Technology

Transcript

  1. What does it mean testable? • Test it quickly during

    development • Test units in isolation • There’s a way to provide mocks
  2. “Standard” Android app • check Android SDK samples & documentation

    • or Google’s iosched app • business logic in Activities, Fragments, Services, … • view and presenter effectively mixed together
  3. Android APIs • difficult to test and mock • we

    don’t have creation of Android components under control
  4. Abstracting Android APIs • we need some boilerplate to get

    away • remove all business logic from Android component classes • isolate business logic into presenters, managers, POJOs, … • when possible use MVP pattern
  5. Clean code • try to write clean code • avoid

    methods having hundreds of lines • avoid Activities/Fragments having thousands of lines
  6. And how to test it? • our presenters, POJOs, managers,

    providers, etc. are simple to test • Android components are stripped off of business logic • nothing important to test remains there
  7. Android Unit Tests • Added rather recently • You need

    some work to make them really useful. • Dependency injection • Mocking
  8. Dagger 2 • by Google • evolution of Dagger 1

    (by Square) • no reflection • generated code in compile time • constructor and field injection
  9. Dagger 2 • Constructor injection private ProviderC mProviderC;
 private ProviderD

    mProviderD;
 
 @Inject
 public ProviderA(ProviderC providerC, ProviderD providerD) {
 mProviderC = providerC;
 mProviderD = providerD;
 }
  10. Dagger 2 • Field injection public class MainActivity extends AppCompatActivity

    {
 @Inject ProviderA mProviderA;
 @Inject ProviderB mProviderB; @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState); 
 ((MyApp) getApplication()).getAppComponent() .injectMainActivity(this); } }
  11. Dagger 2 • prefer constructor injection wherever possible • you

    can test the unit in isolation • providing mocks is a piece of cake
  12. Dagger 2 • Some catches when using field injection •

    Construct the whole component • Implicit provisions doesn’t support overrides!! public class ProviderA { … @Inject
 public ProviderA(ProviderC providerC) {
 mProviderC = providerC;
 } }
  13. Dagger 2 • Some catches when using field injection •

    Make explicit provisions @Module
 public class AppModule {
 
 @Provides @Singleton
 ProviderB provideProvider2(ProviderC providerC) {
 return new ProviderB(providerC);
 }
 
 @Provides
 ProviderD provideProvider4() {
 return new ProviderD();
 }
 } • Beware marking constructors with @Inject when providing explicitly • may create unwanted double provision
  14. Mocking • Android framework has some historical things • package

    android.test.mock • for instrumentation tests
  15. Android APIs & Unit Test • historically • java.lang.RuntimeException: Stub!

    • now • mockable android.jar • Method ... not mocked.
  16. @RunWith(JUnit4.class)
 public class ProviderATest {
 
 @Mock ProviderC mProviderC;
 


    @Mock ProviderD mProviderD;
 
 ProviderA mProviderA;
 
 @Before
 public void setUp() throws Exception {
 MockitoAnnotations.initMocks(this);
 Mockito.when(mProviderC.getString()).thenReturn("hello");
 Mockito.when(mProviderD.getString()).thenReturn("world");
 mProviderA = new ProviderA(mProviderC, mProviderD);
 } … }
  17. Static methods • avoid it as much as possible •

    things like TextUtils.isEmpty() can be painful • alternatives, e.g. Apache commons StringUtils.isEmpty() • PowerMock to the rescue • still better to avoid static
  18. Negatives? • increase the number of methods and classes •

    duplication of Android interfaces/classes • bloated constructors with lots of dependencies
  19. Dev App Builds • How to use dev overrides in

    dev buils? • utilize Android’s Gradle build • Product Flavors can be used for that
  20. Q&A