Android 用匕首和机器人注入服务

Android 用匕首和机器人注入服务,android,dependency-injection,robolectric,dagger,Android,Dependency Injection,Robolectric,Dagger,我正试图用Dagger注入服务TelephonyManager。我正在关注这个。我扩展了Application类来创建图形,并定义了一个ApplicationModule,其中包括ServiceModule,将来还将包括其他模块 编辑: 现在,系统服务被注入到活动中,没有任何问题。我缺少查找应用程序。在活动中插入(此)。它有一个注入,但在使用Robolectric进行测试时仍然没有注入。我在本文底部添加了测试用例: 编辑-2: ApplicationModule删除并创建BaseActivity

我正试图用Dagger注入服务
TelephonyManager
。我正在关注这个。我扩展了
Application
类来创建图形,并定义了一个
ApplicationModule
,其中包括
ServiceModule
,将来还将包括其他模块

编辑:

现在,系统服务被注入到
活动中,没有任何问题。我缺少
查找应用程序。在
活动中插入(此)
。它有一个注入,但在使用
Robolectric
进行测试时仍然没有注入。我在本文底部添加了测试用例:

编辑-2:
ApplicationModule
删除并创建
BaseActivity

((FinderApplication) getApplication()).getGraph().inject(this);
onCreate
方法上。我得到的错误是:

原因:java.lang.NoSuchMethodException:ServiceModule。()

但是如果我定义一个空构造函数,当需要注入类时,我会得到一个空指针

FinderApplication.java

public class FinderApplication extends Application {
    private ObjectGraph mObjectGraph;

    @Override
    public final void onCreate() {
        super.onCreate();
        mObjectGraph = ObjectGraph.create(new ServiceModule(this));
    }

    public final ObjectGraph getGraph() {
        return mObjectGraph;
    }
}
@Module(entryPoints = { SimCardActivity.class, SimService.class })
public class ServiceModule {

    private Context mContext;

    public ServiceModule(Context context) {
        mContext = context;
    }

    @Provides @Singleton
    TelephonyManager provideTelephonyManager(){
        return (TelephonyManager) mContext
            .getSystemService(Context.TELEPHONY_SERVICE);
    }
}
@RunWith(RobolectricTestRunner.class)
public class SimCardActivityTest { 

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

    @Module(
            includes = ServiceModule.class,
            overrides = true,
            entryPoints = {SimCardActivityTest.class, SimCardActivity.class}
    )
    static class TestModule{
        public static TelephonyManager TELEPHONY_MANAGER = 
            Mockito.mock(TelephonyManager.class);

        @Provides @Singleton
        TelephonyManager provideTelephonyManager(){
            return TELEPHONY_MANAGER;
        }
    }
}
ServiceModule.java

public class FinderApplication extends Application {
    private ObjectGraph mObjectGraph;

    @Override
    public final void onCreate() {
        super.onCreate();
        mObjectGraph = ObjectGraph.create(new ServiceModule(this));
    }

    public final ObjectGraph getGraph() {
        return mObjectGraph;
    }
}
@Module(entryPoints = { SimCardActivity.class, SimService.class })
public class ServiceModule {

    private Context mContext;

    public ServiceModule(Context context) {
        mContext = context;
    }

    @Provides @Singleton
    TelephonyManager provideTelephonyManager(){
        return (TelephonyManager) mContext
            .getSystemService(Context.TELEPHONY_SERVICE);
    }
}
@RunWith(RobolectricTestRunner.class)
public class SimCardActivityTest { 

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

    @Module(
            includes = ServiceModule.class,
            overrides = true,
            entryPoints = {SimCardActivityTest.class, SimCardActivity.class}
    )
    static class TestModule{
        public static TelephonyManager TELEPHONY_MANAGER = 
            Mockito.mock(TelephonyManager.class);

        @Provides @Singleton
        TelephonyManager provideTelephonyManager(){
            return TELEPHONY_MANAGER;
        }
    }
}
SimCardActivityTest.java

public class FinderApplication extends Application {
    private ObjectGraph mObjectGraph;

    @Override
    public final void onCreate() {
        super.onCreate();
        mObjectGraph = ObjectGraph.create(new ServiceModule(this));
    }

    public final ObjectGraph getGraph() {
        return mObjectGraph;
    }
}
@Module(entryPoints = { SimCardActivity.class, SimService.class })
public class ServiceModule {

    private Context mContext;

    public ServiceModule(Context context) {
        mContext = context;
    }

    @Provides @Singleton
    TelephonyManager provideTelephonyManager(){
        return (TelephonyManager) mContext
            .getSystemService(Context.TELEPHONY_SERVICE);
    }
}
@RunWith(RobolectricTestRunner.class)
public class SimCardActivityTest { 

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

    @Module(
            includes = ServiceModule.class,
            overrides = true,
            entryPoints = {SimCardActivityTest.class, SimCardActivity.class}
    )
    static class TestModule{
        public static TelephonyManager TELEPHONY_MANAGER = 
            Mockito.mock(TelephonyManager.class);

        @Provides @Singleton
        TelephonyManager provideTelephonyManager(){
            return TELEPHONY_MANAGER;
        }
    }
}

正如@AndyDennie在他的评论中所说,我在测试课上没有做任何注入。注入被测活动而不是在
setUp()上创建它解决了问题

我当前的测试用例(相关代码)如下所示:

@RunWith(RobolectricTestRunner.class)
public class SimCardActivityTest {

    @Inject
    private SimCardActivity mActivity;

    private TelephonyManager mTelephonyManager;

    @Before
    public void setUp() throws Exception {
        ObjectGraph.create(new ServiceModule(Robolectric.application), 
                           new ServiceTestModule()).inject(this);
    }

    @Module(
            includes = {ServiceModule.class },
            overrides = true,
            entryPoints = {SimCardActivity.class, SimCardActivityTest.class}
    )
    static class ServiceTestModule {
        public static TelephonyManager TELEPHONY_MANAGER = 
            Mockito.mock(TelephonyManager.class);

        @Provides
        @Singleton
        TelephonyManager provideTelephonyManager(){
            return TELEPHONY_MANAGER;
        }
    }
}

我认为@Module注释中的includes标志不会为其他模块提供成员。“包含”用于使用另一个模块来确保满足每个入口点中的所有可注入成员,以便该模块创建一个完整的对象图。因为在应用程序正常运行时正在注入。您可能正在将测试用例注入到对象图而不是活动中?这并不能解释您看到的错误,但我认为在您的安装方法中创建的对象图实际上没有用于任何用途。您可以使用它来调用inject(this),但SimCardActivityTest没有依赖项,因此您没有在那里注入任何内容。我认为您需要在FinderApplication上使用setObjectGraph方法,然后您需要从安装程序中调用它。@AndyDennie您是对的,我认为它们是两个完全不同的图。我需要做的是在SimCardActivity中注入一个模拟对象。次要注释:我相信如果为TelephonyManager提供@Singleton,则不需要声明一个静态实例(TELEPHONY_MANAGER)并返回它。您可以在提供的方法中直接返回Mockito.mock(TelephonyManager.class),因为它只执行一次。