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

Mock Partially using Dagger

Mock Partially using Dagger

How to mock partially using Dagger 2

Fumihiko Shiroyama

May 09, 2017
Tweet

More Decks by Fumihiko Shiroyama

Other Decks in Programming

Transcript

  1. Mock Partially
    @fushiroyama

    View Slide

  2. Android Testing Bootcamp
    • https://android-testing-
    bootcamp.connpass.com/
    • https://android-testing-
    bootcamp.connpass.com/event/55274/

    View Slide

  3. TL;DR
    • Use Dagger2
    • Make Partial Component
    • Use it as Component Dependency
    • Write Mock Module of that Component
    • Prepare Test Application class
    • Specify it in Custom Test Runner

    View Slide

  4. Normal Way

    View Slide

  5. Application Module
    @Module
    public class ApplicationModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  6. Application Module
    @Module
    public class ApplicationModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  7. Application Module
    @Module
    public class ApplicationModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  8. Application Component
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  9. Application Component
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  10. Application Component
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  11. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  12. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  13. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  14. Partial Mock

    View Slide

  15. Application Module
    @Module
    public class ApplicationModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  16. Application Module
    @Module
    public class ApplicationModule {
    // removed
    }

    View Slide

  17. API Module
    @Module
    public class ApiModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  18. API Module
    @Module
    public class ApiModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  19. API Module
    @Module
    public class ApiModule {
    @Provides public Info providesInfo() {
    return Info.newInstance();
    }
    @Provides public Auth providesAuth() {
    return Auth.newInstance();
    }
    }

    View Slide

  20. API Component
    @Component(modules = ApiModule.class)
    public interface ApiComponent {
    Info getInfo();
    Auth getAuth();
    }

    View Slide

  21. API Component
    @Component(modules = ApiModule.class)
    public interface ApiComponent {
    Info getInfo();
    Auth getAuth();
    }

    View Slide

  22. API Component
    @Component(modules = ApiModule.class)
    public interface ApiComponent {
    Info getInfo();
    Auth getAuth();
    }

    View Slide

  23. API Component
    @Component(modules = ApiModule.class)
    public interface ApiComponent {
    Info getInfo();
    Auth getAuth();
    }
    /FDFTTBSZ

    View Slide

  24. Component Dependency

    View Slide

  25. Application Component
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  26. Application Component
    @Component(modules = ApplicationModule.class)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  27. Application Component
    @Component(modules = ApplicationModule.class,
    dependencies = ApiComponent.clas)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  28. Application Component
    @Component(modules = ApplicationModule.class,
    dependencies = ApiComponent.clas)
    public interface ApplicationComponent {
    ActivityComponent plus(ActivityModule module);
    void inject(Foo foo);
    void inject(Bar bar);
    }

    View Slide

  29. Custom Application

    View Slide

  30. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  31. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    ApiComponent apiComponent = DaggerApiComponent.builder()
    .apiModule(new ApiModule())
    .build();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(apiComponent)
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  32. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    ApiComponent apiComponent = DaggerApiComponent.builder()
    .apiModule(new ApiModule())
    .build();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(apiComponent)
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  33. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    ApiComponent apiComponent = DaggerApiComponent.builder()
    .apiModule(new ApiModule())
    .build();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(apiComponent)
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  34. My Application
    @Override
    public void onCreate() {
    super.onCreate();
    ApiComponent apiComponent = DaggerApiComponent.builder()
    .apiModule(new ApiModule())
    .build();
    applicationComponent = DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(apiComponent)
    .build();
    }
    public ApplicationComponent getApplicationComponent() {
    return applicationComponent;
    }

    View Slide

  35. Mock API Module

    View Slide

  36. Mock API Module
    @Module
    public class MockApiModule {
    private final Auth mockAuthApi;
    private final Info mockInfoApi;
    public MockApiModule() {
    mockAuthApi = Mockito.mock(Auth.class);
    mockInfoApi = Mockito.mock(Info.class);
    }
    @Provides Info providesInfo() {
    return mockInfoApi;
    }
    @Provides public Auth providesAuth() {
    return mockAuthApi;
    }
    }

    View Slide

  37. Mock API Module
    @Module
    public class MockApiModule {
    private final Auth mockAuthApi;
    private final Info mockInfoApi;
    public MockApiModule() {
    mockAuthApi = Mockito.mock(Auth.class);
    mockInfoApi = Mockito.mock(Info.class);
    }
    @Provides Info providesInfo() {
    return mockInfoApi;
    }
    @Provides public Auth providesAuth() {
    return mockAuthApi;
    }
    }

    View Slide

  38. Mock API Component

    View Slide

  39. Mock API Component
    @Component(modules = MockApiModule.class)
    public interface MockApiComponent extends ApiComponent {
    }

    View Slide

  40. Mock API Component
    @Component(modules = MockApiModule.class)
    public interface MockApiComponent extends ApiComponent {
    }

    View Slide

  41. Mock API Component
    @Component(modules = MockApiModule.class)
    public interface MockApiComponent extends ApiComponent {
    }

    View Slide

  42. Test Application

    View Slide

  43. Test Application
    public class TestApplication extends MyApplication {
    @Override
    public ApplicationComponent getApplicationComponent() {
    MockApiComponent mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    }

    View Slide

  44. Test Application
    public class TestApplication extends MyApplication {
    @Override
    public ApplicationComponent getApplicationComponent() {
    MockApiComponent mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    }

    View Slide

  45. Test Application
    public class TestApplication extends MyApplication {
    @Override
    public ApplicationComponent getApplicationComponent() {
    MockApiComponent mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    }

    View Slide

  46. Test Application
    public class TestApplication extends MyApplication {
    @Override
    public ApplicationComponent getApplicationComponent() {
    MockApiComponent mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    }

    View Slide

  47. Test Application
    public class TestApplication extends MyApplication {
    private MockApiComponent mockApiComponent;
    @Override
    public ApplicationComponent getApplicationComponent() {
    mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    public MockApiComponent getMockApiComponent() {
    return mockApiComponent;
    }
    }

    View Slide

  48. Test Application
    public class TestApplication extends MyApplication {
    private MockApiComponent mockApiComponent;
    @Override
    public ApplicationComponent getApplicationComponent() {
    mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    public MockApiComponent getMockApiComponent() {
    return mockApiComponent;
    }
    }

    View Slide

  49. Test Application
    public class TestApplication extends MyApplication {
    private MockApiComponent mockApiComponent;
    @Override
    public ApplicationComponent getApplicationComponent() {
    mockApiComponent = DaggerMockApiComponent.builder()
    .mockApiModule(new MockApiModule())
    .build();
    return DaggerApplicationComponent.builder()
    .applicationModule(new ApplicationModule(this))
    .apiComponent(mockApiComponent)
    .build();
    }
    public MockApiComponent getMockApiComponent() {
    return mockApiComponent;
    }
    }

    View Slide

  50. Mock Test Runner

    View Slide

  51. Mock Test Runner
    public class MockTestRunner extends AndroidJUnitRunner {
    @Override
    public Application newApplication(ClassLoader cl, String className, Context context)
    throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    String testApplicationClassName = TestApplication.class.getCanonicalName();
    return super.newApplication(cl, testApplicationClassName, context);
    }
    }

    View Slide

  52. Mock Test Runner
    public class MockTestRunner extends AndroidJUnitRunner {
    @Override
    public Application newApplication(ClassLoader cl, String className, Context context)
    throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    String testApplicationClassName = TestApplication.class.getCanonicalName();
    return super.newApplication(cl, testApplicationClassName, context);
    }
    }

    View Slide

  53. Mock Test Runner
    public class MockTestRunner extends AndroidJUnitRunner {
    @Override
    public Application newApplication(ClassLoader cl, String className, Context context)
    throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    String testApplicationClassName = TestApplication.class.getCanonicalName();
    return super.newApplication(cl, testApplicationClassName, context);
    }
    }

    View Slide

  54. Write Your Test!

    View Slide

  55. Your Android Test
    @RunWith(AndroidJUnit4.class)
    public class YourAndroidTest {
    @Before
    public void setUp() throws Exception {
    TestApplication application = (TestApplication)
    InstrumentationRegistry.getTargetContext().getApplicationContext();
    MockApiComponent mockApiComponent = application.getMockApiComponent();
    Info info = mockApiComponent.getInfo();
    when(info.access(any())).thenReturn(result);
    }
    @Test
    public void doYourTest() { }
    }

    View Slide

  56. Your Android Test
    @RunWith(AndroidJUnit4.class)
    public class YourAndroidTest {
    @Before
    public void setUp() throws Exception {
    TestApplication application = (TestApplication)
    InstrumentationRegistry.getTargetContext().getApplicationContext();
    MockApiComponent mockApiComponent = application.getMockApiComponent();
    Info info = mockApiComponent.getInfo();
    when(info.access(any())).thenReturn(result);
    }
    @Test
    public void doYourTest() { }
    }

    View Slide

  57. Your Android Test
    @RunWith(AndroidJUnit4.class)
    public class YourAndroidTest {
    @Before
    public void setUp() throws Exception {
    TestApplication application = (TestApplication)
    InstrumentationRegistry.getTargetContext().getApplicationContext();
    MockApiComponent mockApiComponent = application.getMockApiComponent();
    Info info = mockApiComponent.getInfo();
    when(info.access(any())).thenReturn(result);
    }
    @Test
    public void doYourTest() { }
    }

    View Slide

  58. Your Android Test
    @RunWith(AndroidJUnit4.class)
    public class YourAndroidTest {
    @Before
    public void setUp() throws Exception {
    TestApplication application = (TestApplication)
    InstrumentationRegistry.getTargetContext().getApplicationContext();
    MockApiComponent mockApiComponent = application.getMockApiComponent();
    Info info = mockApiComponent.getInfo();
    when(info.access(any())).thenReturn(result);
    }
    @Test
    public void doYourTest() { }
    }

    View Slide

  59. Your Android Test
    @RunWith(AndroidJUnit4.class)
    public class YourAndroidTest {
    @Before
    public void setUp() throws Exception {
    TestApplication application = (TestApplication)
    InstrumentationRegistry.getTargetContext().getApplicationContext();
    MockApiComponent mockApiComponent = application.getMockApiComponent();
    Info info = mockApiComponent.getInfo();
    when(info.access(any())).thenReturn(result);
    }
    @Test
    public void doYourTest() { }
    }

    View Slide

  60. Use Your Runner
    android {
    defaultConfig {
    testInstrumentationRunner "your.package.runner.MockTestRunner"
    }
    }

    View Slide

  61. Thank you!

    View Slide