我有一个Presenter
类使用通过Dagger注入的字段,它看起来像这样:
public class RssListPresenter {
@Inject
RssService rssService; // <-- injected field
public RssListPresenter() {
setupDI();
}
private void setupDI() {
DaggerNetworkComponent.builder()
.networkModule(new NetworkModule())
.build()
.inject(this);
}
public void loadItems() {
Rss rss = rssService.getRssFeed()
// ....
}
}
一切正常。现在,我想对RssListPresenter
类进行单元测试。问题是我如何向演示者提供模拟RssService
?
当然我可以向演示者添加一个新方法setRssService(RssService rssService)
并使用它来提供单元测试的模拟,但是仅为单元测试添加此方法感觉不对。处理这个问题的正确方法是什么?
为了完整性,这里是模块和组件声明:
@Singleton
@Component(modules = NetworkModule.class)
public interface NetworkComponent {
void inject(RssListPresenter presenter);
}
@Module
public class NetworkModule {
@Provides
Retrofit provideRetrofit() {
// ...
}
@Provides
@Singleton
RssService providePcWorldRssService(Retrofit retrofit) {
return retrofit.create(RssService.class);
}
}
答案 0 :(得分:6)
属性注入就像测试那么容易。在这种情况下,构造函数注入要好得多。将构造函数重构为如下所示:
var myObject1 = function() {
var x = 0;
return{}
}();
var myObject2 = function() {
return{
increment: function() {
myObject1.x +=1;
console.log(myObject1.x);
}
}
}();
myObject2.increment();
现在您可以轻松地进行测试:
private final RssService rssService;
@Inject
public RssListPresenter(RssService rssService) {
this.rssService = rssService;
}
您可能不应该在//mocks
RssService mockRssService;
//system under test
RssListPresenter rssListPresenter;
@Before
public void setup() {
mockRssService = Mockito.mock(RssService.class);
rssListPresenter = new RssListPresenter(mockRssService);
}
内使用DaggerNetworkComponent.inject(this)
。相反,您应该配置dagger,以便在将成员注入顶级类(RssListPresenter
,Activity
,Fragment
)时,它可以访问对象图并创建{的实例{1}}。
为什么只将注射器放在Service
和RssPresenter
而不是Activity
?这些是由Android系统实例化的类,因此您别无选择,只能使用注入器。
澄清一下,Service
,RssListPresenter
等是理想的注射目标。 Activity
等注入依赖项。您需要配置依赖注入框架,dagger,以便它可以提供正确的依赖关系以注入注入目标。
因此,您还需要为Fragment
RssListPresenter
方法
@Provides
答案 1 :(得分:0)
您的课程违反了某些S.O.L.I.D
原则,这使得对其进行单元测试非常困难。您的班级肯定违反了SRP(单一责任原则),因为它有多个的原因需要更改。还存在可能的依赖性倒置违规。
我建议重新考虑类的模型,以便每个类执行特定的功能,并有一个改变的理由。