Dagger 2 Android子组件覆盖

时间:2017-10-12 13:57:47

标签: android android-testing dagger-2 android-espresso

如果我创建一个我想在dagger特定功能中使用的子组件,请说:

@TransactionsActivityScope
@Subcomponent(modules = {TransactionsModule.class})
public interface TransactionsComponent {

    TransactionsManager provideTransactionsManager();

    void inject(TransactionsFragment transactionsFragment);

    void inject(TransactionsFilterActivity transactionsFilterActivity);
}

我在主应用组件中添加了一个加号:

TransactionComponent plusTransactionSubcomponent(TransactionModule transactionModule);

并在片段中使用它: public class TransactionsFragment { .. .. ..

 @Override
    protected void setupGraph(DaggerAppGraph graph) {
        graph.plusTransactionsSubcomponent(new TransactionModule()).inject(this);
    }
}

在Espresso测试中覆盖此子组件的正确方法是什么。 对于组件和组件依赖关系,您可以直接编写一个扩展“原始”组件的TestAppComponent并在其中打出MockModule,但如何使用子组件干净地完成此操作?

我还看了一下Dagger的AndroidInjector.inject(这个);组件和活动组件的解决方案是类似的,但我认为没有办法干净地为子组件和片段做到这一点。 我认为编写方法并覆盖Activity / Fragments组件setter并在那里进行覆盖是不理想的。 我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

这在原始的Dagger上很容易,但是没有使用Dagger 2.但是,这里有解决方案:创建一个模拟的风格和一个具有完全相同的类名,文件名和位置的模拟模块。现在使用模拟的味道运行你的ui测试。

您可以在test project中看到它是如何完成的。

我的模拟模块然后引用FakeContentRepository,正如您计划的那样。

在build.gradle中:

flavorDimensions "api", "mode"
productFlavors {
   dev21 {
       // min 21 has faster build times, also with instant build
       minSdkVersion 21
       dimension "api"
   }
   dev16 {
        minSdkVersion 16
        dimension "api"
   }
   mock {
        dimension "mode"
   }
   prod {
        minSdkVersion 16
        dimension "mode"
   }
}


// remove mockRelease:
android.variantFilter { variant ->
    if (variant.buildType.name == 'release'
            && variant.getFlavors().get(1).name == 'mock') {
        variant.setIgnore(true);
    }
}

再次:this test project显示一切。

答案 1 :(得分:0)

在我们的应用程序中,我们使用额外的包装器来管理名为ComponentStorage的子组件范围。我们的Application创建此对象,TestApplication会覆盖它并返回TestComponentStorage。因此,我们可以轻松覆盖方法plusTransactionSubcomponent并使用模拟模块返回组件。

public class ComponentStorage {
    protected TransactionComponent transactionComponent;
    protected AppGraph graph;

    public ComponentStorage() {
        graph = buildGraph();
    }

    public TransactionComponent plusTransactionSubcomponent(TransactionModule transactionModule) {
        if(transactionComponent == null) {
            transactionComponent = graph.plusTransactionsSubcomponent(new TransactionModule());
        }
        return transactionComponent;
    }

    public AppGraph buildGraph() {
        return DaggerAppGraph.create();
    }

    // to manage scope manually
    public void clearTransactionSubcomponent() {
        transactionComponent = null;
    }
}


public class TestComponentStorage extends ComponentStorage{

    @Override
    public TransactionComponent plusTransactionSubcomponent(TransactionModule transactionModule) {
        if(transactionComponent == null) {
                                                                        // mocked module
            transactionComponent = graph.plusTransactionsSubcomponent(new TestTransactionModule());
        }
        return transactionComponent;
    }
}

在客户端代码中,您将使用它componentStorage.plusTransactionsSubcomponent(new TransactionModule()).inject(this)

如果您需要完整的代码,请留下评论我将为此创建要点。