如何在Android中应用“问,不看”?

时间:2015-11-20 15:29:40

标签: android unit-testing android-testing

这个Google Testing Blog post列出了一些使代码可测试的策略。一个项目部分说:

  

询问事物,不要寻找东西(又名Demeterdency Injection / Demeter法则):好的,你在应用程序代码中删除了新的操作符。但是我如何获得依赖关系。简单:只需要​​在构造函数中询问所需的所有协作者。

换句话说,这样做:

grid = np.zeros((8,8))
for value in range(0,len(xy_new[:,1])):  
    grid[xy_new[value][1],xy_new[value][0]] += 1

不是这个:

Foo(final Bar bar) {
  mBar = bar;
}

原因很明显:它允许您通过传递模拟Foo() { mBar = Bar.getBar(); // or new Bar(); } 来测试Foo。由于Android组件需要no-arg构造函数,因此通过额外的Bar传递它们的参数。

当组件需要的内容不是BundleParcelable时,如何在Android中应用此原则?

1 个答案:

答案 0 :(得分:1)

我使用的是Dagger2,您只需要依赖对象图(或其子视图扩展子图之一)来接收所有依赖项。

含糊不清就像这样,

  • 的Singleton

@Component(modules={SingletonModule.class})
@Singleton
public interface SingletonComponent {
    Foo foo();
    Bar bar();

    void inject(MainActivity mainActivity);
}

@Module
public class SingletonModule {
    @Provides
    @Singleton
    public Bar bar() {
        return new Bar();
    }

    @Provides
    @Singleton
    public Foo foo(Bar bar) {
        return new Foo(bar);
    }
}

public class CustomApplication extends Application {
    SingletonComponent singletonComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        singletonComponent = DaggerSingletonComponent.builder()
                              .singletonModule(new SingletonModule())
                              .build();
    }

    public SingletonComponent getSingletonComponent() {
        return singletonComponent;
    }
}

public class MainActivity extends Activity {
    @Inject
    Foo foo;

    @Inject
    Bar bar;

    @Override
    public void onCreate(Bundle saveinstanceState) {
         super.onCreate(saveinstanceState);
         ((CustomApplication)getApplicationContext()).getSingletonComponent().inject(this);
         bar.doSomething();
         foo.doSomething();
    }
}
  • Subscoping

@Component(modules=SingletonModule.class) 
@Singleton
public interface SingletonComponent {
    Foo foo();
}

@Component(dependencies={SingletonComponent.class}, modules={MainActivityModule.class})
@ActivityScope
public interface MainActivityCompoent extends SingletonComponent {
    Bar bar();

    void inject(MainActivity mainActivity);
}

@Module
public class SingletonModule {
    @Provides
    @Singleton
    public Foo foo() {
        return new Foo();
    }
}

@Module
public class MainActivityModule {
    @Provides
    @ActivityScope
    public Bar bar(Foo foo) {
        return new Bar(foo);
    }
}

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

public class CustomApplication extends Application {
    SingletonComponent singletonComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        singletonComponent = DaggerSingletonComponent.builder()
                              .singletonModule(new SingletonModule())
                              .build();
    }

    public SingletonComponent getSingletonComponent() {
        return singletonComponent;
    }
}

public class MainActivity extends Activity {
    @Inject
    Foo foo;

    @Inject
    Bar bar;

    private MainActivityComponent mainActivityComponent;

    @Override
    public void onCreate(Bundle saveinstanceState) {
         super.onCreate(saveinstanceState);
         mainActivityComponent = DaggerMainActivityComponent.builder()
             .singletonComponent(((CustomApplication)getApplicationContext()).getSingletonComponent())
             .mainActivityModule(new MainActivityModule()) 
             .build();
        mainActivityComponent.inject(this);
        bar.doSomething();
        foo.doSomething();
    }
}