我是匕首的新手,最近我开始在自己的一个项目中使用匕首,因为能够以不同的方式处理依赖注入的概念用于测试和生产,因此能够注入我可以用于测试的模拟对象很棒。

我修改了我的应用程序,以遵循dagger simple-android示例中的样式。

设置完毕后,我发现注入存在问题,并且我无法使用测试逻辑完全超载生产应用程序中的注入。

我正在寻找关于如何设置它的建议,以便我的测试可以实际注入与模拟或其他对象的差异,以便根据需要进行测试,而不是过于愚蠢。 目前, MainActivityTest被正确注入,但是当我们到达MainActivity时 ,它会转到PhoneApplication并使用它的对象图注入

我已经把我下面的内容包括在内了。 任何帮助将不胜感激!


这是我的PhoneApplication ,基于DemoApplication

public class PhoneApplication extends Application {
    private ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();

        graph = ObjectGraph.create(getModules().toArray());
    }

    protected List<Object> getModules() {
        return Arrays.asList(new AndroidModule(this), new PhoneModule());
    }

    public void inject(Object object) {
        graph.inject(object);
    }
}

这是我的AndroidModule

@Module(library = true, injects = MainActivity.class)
public class AndroidModule {
    private final Context context;

    public AndroidModule(Context context) {
        this.context = context;
    }

    /**
     * Allow the application context to be injected but require that it be
     * annotated with {@link ForApplication @Annotation} to explicitly
     * differentiate it from an activity context.
     */
    @Provides
    @Singleton
    @ForApplication
    Context provideApplicationContext() {
        return context;
    }

    @Provides
    @Singleton
    NotificationManager provideNotificationManager() {
        return (NotificationManager) context
                .getSystemService(Application.NOTIFICATION_SERVICE);
    }

    @Provides
    @Singleton
    LocalBroadcastManager provideLocalBroadcastManager() {
        return LocalBroadcastManager.getInstance(context);
    }

    @Provides
    @Singleton
    ContentResolver provideContentResolver() {
        return context.getContentResolver();
    }

}

基于该示例,我还将我的活动设置为使用基本活动。

public abstract class ActionBarBaseActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((PhoneApplication) getApplication()).inject(this);
    }
}

然后在我的MainActivity中,我有以下内容

public class MainActivity extends ActionBarBaseActivity {

...

    @Inject
    LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
...
        try {
            messageReceivedIntentFilter = new IntentFilter(
                    Constants.EVENT_MESSAGE_RECEIVED,
                    "vnd.android.cursor.dir/vnd."
                            + DataProviderContract.AUTHORITY + "."
                            + DataProviderContract.MESSAGES_TABLE_NAME);

            localBroadcastManager.registerReceiver(messageReceiver,
                    messageReceivedIntentFilter);
        } catch (MalformedMimeTypeException e) {
            Log.e(LOG_TAG,
                    "An error occurred registering an Intent for EVENT_MESSAGE_RECEIVED",
                    e);
        }
...
    }
...
}

这很有效,注射很快就到了,我欣喜若狂。 直到我真的想做一些测试。 我想要执行的第一个测试是在我的MainActivity上

在上面的onCreate方法中,我们使用AndroidModule中的LocalBroadcastManager而不是MainActivityTest中的LocalBroadcastManager,因为我们目前没有办法告诉PhoneApplication或活动他们应该使用不同的对象图。

public class MainActivityTest extends
        ActivityInstrumentationTestCase2<MainActivity> {

    @Inject
    NotificationManager notificationManager;

    @Inject
    ContentResolver contentResolver;

    @Inject
    MockContentResolver mockContentResolver;

    @Inject
    LocalBroadcastManager localBroadcastManager;

    private Context context;

    public MainActivityTest() {
        super(MainActivity.class);
    }

    @Module(injects = { MainActivityTest.class, MainActivity.class }, library = true, overrides = true)
    static class MockModule {
        Context context;

        public MockModule(Context context) {
            this.context = context;
        }

        @Provides
        @Singleton
        ContentResolver provideContentResolver() {
            return provideMockContentResolver();
        }

        @Provides
        @Singleton
        MockContentResolver provideMockContentResolver() {
            return new MockContentResolver();
        }

        @Provides
        @Singleton
        LocalBroadcastManager provideLocalBroadcastManager() {
            return Mockito.mock(LocalBroadcastManager.class);
        }
    }

    @Override
    protected void setUp() throws Exception {
        System.setProperty("dexmaker.dexcache", getInstrumentation()
                .getTargetContext().getCacheDir().getPath());

        context = getInstrumentation().getTargetContext();
        ObjectGraph graph = ObjectGraph.create(new AndroidModule(context),
                new MockModule(context));
        graph.inject(this);

        super.setUp();
    };

    @MediumTest
    @UiThreadTest
    public void testIncomingMessageReceiver_onReceive()
            throws MalformedMimeTypeException {

        ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor
                .forClass(BroadcastReceiver.class);
        Mockito.verify(localBroadcastManager, Mockito.atLeastOnce())
                .registerReceiver(receiverCaptor.capture(),
                        Mockito.any(IntentFilter.class));
    }
}

这是一个非常简单的测试,让我开始。 我知道在onCreate中,我们要注册一个BroadcastReceiver,所以让我们确保它已注册。 由于测试具有mockLocalBroadcastManager,但活动使用生产LocalBroadcastManager,因此验证失败。

===============>>#1 票数:0

我不确定。 刚刚通过网络搜索了解如何正确使用匕首进行测试。

然而,据我所知, MainActivity从应用程序中获取其对象图。 所以,这是你必须插入MockModule

为此,您应该创建PhoneApplication的子类并覆盖getModules()方法以返回您的MockModule 之后,您应该使用ActivityUnitTestCase.setApplication()模拟应用程序(您的测试应首先将ActivityUnitTestCase子类化)。 这应该解决问题。

  ask by Jamie Starke translate from so

未解决问题?本站智能推荐:

3回复

如何使用Dagger2将活动范围的依赖项替换为模拟

我的Activity中有一个作用域依赖项,我想用一些模拟测试该活动。 我已经阅读了有关在测试期间建议用测试组件替换Application组件的不同方法,但我想要的是替换Activity组件。 例如,我想在我的MVP设置中测试针对模拟演示者的Activity。 我相信通过调用Acti
1回复

Dagger在产品和测试中向IntentService注入不同的依赖项

是否有可能通过匕首将不同的对象注入android.app.IntentService中,具体取决于它是测试还是生产? 这主要是将WebRequest类注入服务的代码(简化)。 我想编写一个模拟http响应的测试。 我从一个新的模块开始 在测试中,我尝试了以下 }
1回复

在Android中使用匕首注入适配器

我只是想用匕首而不是roboguice,到目前为止,黄油刀很棒而且很简单,这很重要:) 但是另一方面,匕首我发现它的配置比roboguice少,我必须基准测试它是否值得更改,但是在这种情况下,我正在研究如何在适配器中注入一些东西,这就是我所做的,并且可以正常工作: 但是在创建该实例
1回复

匕首与二传手进行测试

我真的才刚刚开始进行android测试,并且我意识到依赖项很难测试。 在我的前几次测试中,我使用了setter来注入一个模拟对象,但是在阅读了一些有关Dagger的内容之后,我正在考虑使用它。 以下是我目前进行的一些测试的示例。 在这种情况下,我要测试的方法依赖于标记对象。 我为该对
1回复

使用来自多个模块的依赖项匕首2.11 android

嗨,我在项目中的域包中有两个模块,并且有使用DaggerAppComponent手动注入自身的firebase insance服务类。 然后,在我提到的两个模块上有两个注入依赖项。 ModuleOne有一个称为存储的依赖关系,而ModuleTwo有一个称为委托者的依赖关系。 当
1回复

Android匕首依赖循环

我有2个具有相同Scope的依赖项,彼此需要。 我的依赖项是使用不同方法的域服务(每种方法都是不同的业务案例)。 某些业务案例可能使用其他域中的方法。 为了做到这一点,我需要domain1可用于domain2,反之亦然。 但是当我这样做时,我得到一个依赖循环编译错误。 谷歌
1回复

无法使用匕首2注入LinearLayout?

嗨,我尝试使用匕首2.11注入LinearLayout,并且出现以下错误: 这是我的应用程序模块 我的课: 注入线性布局失败,但其他所有东西都注入并起作用
2回复

简单的匕首单元测试失败

我是匕首的新手。 我创建了一个非常简单的单元测试,以尝试了解如何使用匕首。 不幸的是它失败了。 我可能还不了解匕首的一些基本原理。 我的测试课失败了 我以为dagger会将B注入A中,因为A希望将其注入并且DaggerModule包含一个@Provides带注释的方法,该方
9回复

匕首和黄油刀与Android注释

我正在评估Android应用程序的依赖注入(DI)框架。 最有力的竞争者是:Dagger(有Butter Knife)和Android Annotations。 据我所知,Dagger和ButterKnife来自同一个源头,他们相互补充。 这是我正在寻找的关键矩阵: 易于使用(我
1回复

匕首多次注入

是否有可能获得匕首中的接口/类的实现列表? 我正在看类似Ninject的Multi-Injection的东西。