[英]Dagger vs a setter for testing
我真的才刚刚开始进行android测试,并且我意识到依赖项很难测试。 在我的前几次测试中,我使用了setter来注入一个模拟对象,但是在阅读了一些有关Dagger的内容之后,我正在考虑使用它。 以下是我目前进行的一些测试的示例。
在这种情况下,我要测试的方法依赖于标记对象。 我为该对象添加了一个setter。 为了测试该方法,我构建了两个不同版本的依赖对象,每个版本都带有标记Object的不同模拟。
正如我所说的,我已经阅读了一些有关依赖注入和Dagger的文章,并且我想我知道如何拥有一个生产模块和一个测试模块,但是我开始考虑使用Dagger完成与以下相同的工作,我需要三个不同的模块。
我是否真的需要3个不同的模块,或者我缺少什么? 将这样的东西转换为使用Dagger而不是setter有意义吗? 如果是这样,有人可以提供有关如何执行此操作的指导吗?
@Test
public void testGetGoogleMapMarkerParametersWithoutAccuracy() {
when(mockRailsMarker.hasAccuracy()).thenReturn(false);
when(mockRailsMarker.getAccuracy()).thenReturn(null);
MapMarker androidMapMarker = new MapMarkerBuilder().withBus(mockBus)
.withMarker(mockRailsMarker)
.build();
assertThat(androidMapMarker.getGoogleMapMarkerParameters().getCircleRadius()).as("radius is zero").isEqualTo(0.0f);
}
@Test
public void testGetGoogleMapMarkerParametersWithAccuracy() {
when(mockRailsMarker.hasAccuracy()).thenReturn(true);
when(mockRailsMarker.getAccuracy()).thenReturn(44.0f);
MapMarker androidMapMarker = new MapMarkerBuilder().withBus(mockBus)
.withMarker(mockRailsMarker)
.build();
assertThat(androidMapMarker.getGoogleMapMarkerParameters().getCircleRadius()).as("has a valid radius").isEqualTo(44.0f);
}
我想我自己找到了解决方案。
在上面的问题中,我正在测试一种方法,该方法依赖于称为RailsMapMarker
的类的实例。我满足该依赖关系的方式是在MapMarkerBuild过程中创建一个模拟并通过setter方法将其“注入”。
在这里用Dagger做同样的事情是我会做的。 我说是,因为事实证明该特定对象已经可以通过构造函数传递,所以这更多是基于我对另一个依赖项所做的示例。
首先,我创建2个模块,一个用于生产,一个用于测试。
生产版本看起来像这样(这在您的主项目中)
@Module(injects = MapMarker.class)
public class AFirstDaggerModule {
@Provides
RailsMapMarker provideRailsMapMarker() {
System.out.println("inside dagger -non mock");
return new RailsMapMarker();
}
}
像这样的测试(请注意@Singleton注释,这会将相同的实例注入到测试类和被测类中)是关键。 (这在您的测试项目中)
@Module(injects = { MapMarker.class, MapMarkerTest.class })
public class AFirstDaggerModule {
@Provides @Singleton
RailsMapMarker provideRailsMapMarker() {
System.out.println("inside dagger - mock");
return mock(RailsMapMarker.class);
}
}
在MapMarker类和MapMarkerTest类中,我都有一个带注释的字段。
MapMarker类
@Inject
RailsMapMarker railsMapMarker;
MapMarkerTest类
@Inject
RailsMapMarker mockRailsMapMarker;
在我的Application类中,我有一个字段,在其中创建图形,并为该图形获取一个getter
private static ObjectGraph objectGraph;
public static ObjectGraph getObjectGraph() {
return objectGraph;
}
在应用程序的onCreate方法中,我有:
objectGraph = ObjectGraph.create(new AFirstDaggerModule());
其中AFirstDaggerModule是应用程序和测试项目中模块的名称
然后,在我正在测试的类的构造函数和测试类的setUp()方法中,我都具有以下内容:
MyApp.getObjectGraph().inject(this);
经过所有这些,当我运行测试时,我正在测试的实例中有一个注入的模拟, 并且我的测试类中有一个字段(mockRailsMarker),该字段引用了该模拟,因为模拟的相同实例被注入了该模拟。这两个字段(由于@Singleton注释)。
这意味着我不需要MapMarker类内的RailsMapMaker对象的setter,因为它现在是由Dagger注入的,并且我可以完全控制我的测试用例的模拟行为。
我知道这对于通常使用Dagger和嘲笑的人来说可能是非常基本的,但是我为此苦了一段时间,而且我从来没有真正找到能将所有细节都放在一个地方的东西。 我发现的大多数内容都假定您知道大部分内容,并展示了其中的一个难题。
无论如何,我希望这对其他人有帮助,否则,当这一切消失时,我至少将能够卷土重来并刷新我的记忆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.