我是Dagger的新手。
TL; DR:
Service
使用Dagger将任何字段注入其中,那么为了实际执行注入,我需要有一个Service
的实例。MyService service = Robolectric.buildService(MyService.class).get()
。然后,objectGraph.inject(service);
MyService
仍使用context.startService(context, MyService.class);
。问题:Dagger解决这种不匹配的惯用方法是什么?
假设我有Service
如下:
public class MyService {
@Inject Parser parser;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String data = intent.getStringExtra("data_to_be_parsed");
parser.parse(data);
}
}
在我的代码中,我有一个ApiClient类来执行此操作:
public class ApiClient{
public static void parseInBackground(Context context, String data){
//This service does not have its fields injected
context.startService(new Intent(context, MyService.class).putExtra("data_to_be_parsed", data));
}
}
将响应用户交互从活动中调用parseInBackground
方法。
现在,我正在关注TDD,因此,我还没有为此编写应用程序模块。这是测试模块:
@Module(injects = MyService.class)
public class TestModule {
@Provides @Singleton Parser provideParser(){
return new MockParser();
}
}
最后,测试用例:
@RunWith(Robolectric.class)
public class ApiTest {
@Test
public void parseInBackground_ParsesCorrectly(){
//This service has its fields injected
MyService service = Robolectric.buildService(MyService.class).get();
ObjectGraph.create(new TestModule()).inject(service);
ApiClient.parseInBackground(Robolectric.application, "<user><name>droid</name></user>");
//Asserts here
}
}
如您所见,在测试中,我检索服务的实例,然后将MockParser
注入其中。但是,ApiClient
类使用Intent直接启动服务。我没有机会进行注射。
我知道我可以MyService
对自己进行注射:
public void onCreate(){
ObjectGraph.create(new TestModule()).inject(this);
}
但是,我在这里硬编码TestModule
。
Dagger中是否存在为这种情况设置依赖关系的习惯用法?
答案 0 :(得分:1)
在测试或服务中对模块进行硬编码的方法是错误的。更好的方法是通过自定义Application
对象执行创建,而ObjectGraph
对象又将保存单个// in MyService class
@Override public void onCreate() {
super.onCreate();
MyApp.from(context).inject(this);
}
// in MyApp class
public static MyApp from(Context context) {
return (MyApp) context.getApplicationContext();
}
//...
private ObjectGraph objectGraph;
@Override public void onCreate() {
// Perform Injection
objectGraph = ObjectGraph.create(getModules());
objectGraph.inject(this);
}
public void inject(Object object) {
objectGraph.inject(object);
}
protected Object[] getModules() {
// return concrete modules based on build type or any other conditions.
}
对象。例如:
overrides=true
或者,您可以将最后一个方法重构为单独的类,并针对不同的flavor或构建类型进行不同的实现。您也可以在TestModule
的注释中设置{{1}}。