在测试中覆盖调试模块

时间:2014-08-12 18:39:06

标签: android dagger

我有一个Gradle应用,其项目结构类似于Jake Wharton's u2020

/src
    /androidTest
    /debug
    /main
    /release

在我的应用程序类中,我构建了Dagger图并注入它:

MyApplication extends Application {
      ...
      public void buildObjectGraphAndInject() {
          Object[] modules = Modules.list(this);
          mApplicationGraph = ObjectGraph.create(modules);
          mApplicationGraph.inject(this);
      }
      ...
}

在调试源集内部,我将Modules.list()定义为:

public final class Modules {
  public static Object[] list(MyApplication app) {
    return new Object[] {
        new AppModule(app),
        new DebugAppModule()
    };
  }

  private Modules() {
    // No instances.
  }
}

在发布源集中,我定义了相同的东西减去DebugAppModule:

public final class Modules {
  public static Object[] list(MyApplication app) {
    return new Object[] {
            new AppModule(app)
    };
  }

  private Modules() {
    // No instances.
  }
}

更深入了解我的依赖图,我创建了一个MockRestAdapter,我可以在运行调试版时使用它:

@Module(
    complete = false,
    library = true,
    overrides = true
)
public final class DebugApiModule {

  @Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) {
    return Endpoints.newFixedEndpoint(apiEndpoint.get());
  }

  @Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) {
    MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter);
    AndroidMockValuePersistence.install(mockRestAdapter, preferences);
    return mockRestAdapter;
  }

  @Provides @Singleton MyApi provideMyApi(RestAdapter restAdapter, MockRestAdapter mockRestAdapter,
                                          @IsMockMode boolean isMockMode, MockMyApi mockService) {
    if (isMockMode) {
      return mockRestAdapter.create(MyApi.class, mockService);
    }
    return restAdapter.create(MyApi.class);
  }

}

但是当我正在运行测试时,我想用一个如下所示的TestApiModule覆盖DebugApiModule:

@Module(
    complete = false,
    library = true,
    overrides = true
)
public final class TestApiModule {

  @Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) {
    return Endpoints.newFixedEndpoint(apiEndpoint.get());
  }

  @Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) {
    MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter);
    mockRestAdapter.setDelay(0);
    mockRestAdapter.setErrorPercentage(0);
    mockRestAdapter.setVariancePercentage(0);
    return mockRestAdapter;
  }

  @Provides @Singleton MyApi provideMyApi(MockRestAdapter mockRestAdapter, MockHnApi mockService) {
      return mockRestAdapter.create(MyApi.class, mockService);
  }

}

实现这一目标的最佳方法是什么?我是否需要像这样创建TestAppModule

public final class Modules {
  public static Object[] list(MyApplication app) {
    return new Object[] {
        new AppModule(app),
        new TestAppModule()
    };
  }

  private Modules() {
    // No instances.
  }
}

并将所有DebugFooModule替换为TestFooModules?如果是这样,我如何解决Modules.java重复的事实?还是我离开基地?

编辑:解决方案

我最终做的是在我的测试setUp中替换应用程序级别的图形(创建MockRestAdapter的地方)

protected void setUp() throws Exception {
  super.setUp();
  HnApp app = HnApp.getInstance();
  app.buildObjectGraphAndInject(TestModules.list(app));
  getActivity();
}

1 个答案:

答案 0 :(得分:1)

我迄今为止做过的事情(我并不完全确定这会扩展)是在我的测试中创建一个静态测试模块类。

   @Module(
            injects = {
                    SharedPreferences.class
    })

      static  class TestModule {
            @Provides @Singleton SharedPreferences provideSharedPreferences(){
                return Mockito.mock(SharedPreferences.class);
            }
    }

在setup()方法中,我注入了测试模块

  @Before
    public  void setUp(){
        ObjectGraph.create(new TestModule()).inject(this);
}

然后@Inject模拟的类:

@Inject SharedPreferences sharedPreferences;