我希望我的代码可测试且灵活,我无法选择是否需要将所有依赖项显式传递给演示者的构造函数,或者最好只将View接口传递给构造函数并在其中注入所有依赖项。
答案 0 :(得分:3)
这是一种理想的模式。
每次有权访问对象构造函数时,都应该在构造函数或其他方法中注入依赖项。 @Inject
注释主要用于在对象内部使用,不是由您创建的。
在构造函数中注入所有依赖项时,在测试期间,您会在初始化期间将所有依赖项传递给模型。因此,每个测试可能包含不同的依赖项和创建的类的不同实例。这也是单元测试的目的 - 为每次测试提供沙箱。
使用Mockito
模拟依赖项也更容易。
请记住,在单元测试中,您不会依赖任何框架配置。单元测试通常包含已创建的模型,仅此而已。一切都必须由你创建(或由框架嘲笑)
以下是一个样本单元测试,证明了上述陈述:
@RunWith(MockitoJUnitRunner.class)
public class GetAreasUseCaseTest {
@Mock ApiManager mApiManager;
@Mock DatabaseManager mDatabaseManager;
private GetAreasUseCase mGetAreasUseCase;
@Rule
public final RxSchedulersOverrideRule mOverrideSchedulersRule = new RxSchedulersOverrideRule();
@Before
public void setUp() {
mGetAreasUseCase = new GetAreasUseCase(mApiManager,
mDatabaseManager);
doReturn(Observable.empty())
.when(mDatabaseManager)
.insertAreas(any(Area.class));
}
@Test
public void testGetAreasUseCaseApiInteraction() throws Exception {
TestSubscriber<List<Area>> testSubscriber = new TestSubscriber<>();
setCorrectApiResponse();
boolean input = true;
Observable testedObservable = mGetAreasUseCase.build(input);
testedObservable.subscribe(testSubscriber);
verify(mApiManager).getAreas(anyLong());
}
}
正如您所看到的,测试结构非常清晰。众所周知,被嘲笑的是什么以及测试了哪个对象。您可以控制依赖项的行为。
如果您计划仅进行检测测试,则会在测试中为您提供ApplicationContext
,并且Dagger
已正确初始化。这里没有区别。当然,您仍然可以模仿Module
和Component
的行为并提供自定义对象的模拟而不是真实的类(Example)
答案 1 :(得分:-1)
这不是一个糟糕的做法,但很难在以后的更改中更改代码。如果您想为演示者添加新的依赖项,该怎么办?然后你必须改变代码中的几乎所有内容。
实际上你要做的事情叫做依赖注入,最好的做法是做依赖注入,使用像Dagger这样的库。我认为Dagger是迄今为止最强大的依赖注入库。您将编写一些提供依赖项的方法,Dagger会在您希望它们使用@inject Annotation时为您提供这些方法。有关完整说明,请参阅此链接: