繁体   English   中英

匕首与二传手进行测试

[英]Dagger vs a setter for testing

我真的才刚刚开始进行android测试,并且我意识到依赖项很难测试。 在我的前几次测试中,我使用了setter来注入一个模拟对象,但是在阅读了一些有关Dagger的内容之后,我正在考虑使用它。 以下是我目前进行的一些测试的示例。

在这种情况下,我要测试的方法依赖于标记对象。 我为该对象添加了一个setter。 为了测试该方法,我构建了两个不同版本的依赖对象,每个版本都带有标记Object的不同模拟。

正如我所说的,我已经阅读了一些有关依赖注入和Dagger的文章,并且我想我知道如何拥有一个生产模块和一个测试模块,但是我开始考虑使用Dagger完成与以下相同的工作,我需要三个不同的模块。

  1. 生产模块-提供实物
  2. 测试模块1-提供配置为返回hasAccuracy()= false和getAccurracy = null的模拟对象
  3. 测试模块2-提供配置为返回hasAccuracy()= true和getAccruacy = 44.0f的模拟对象

我是否真的需要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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM