使用DBUnit / Junit测试我的REPOSITORY层,我应该手动构建方案还是自动化它?什么是优势?

时间:2017-11-13 15:20:31

标签: java spring unit-testing junit dbunit

我在考虑如何为基于java的存储库设计单元测试并遇到设计问题: 让我们假设我有一个Consumer表,其中包含与我的消费者相关的数据: {ID,姓名,电话} 我的ConsumerRepository扩展了BaseRepository,它扩展了JPA repo并支持 findByPhone,findByName,findAll查询和保存选项。

我正在使用H2 in-memo DB和DBUnit进行这些测试,所有测试都在配置并运行,并且正在考虑这个问题:

  1. 当我向内存数据库启动数据时,我是应该使用ConsumerTestData.xml(DBUnit)配置数据并手动为每个测试添加消费者数据,例如:

    <dataset>
    <CONSUMER CONSUMER_ID="1" FIRST_NAME="Elvis" LAST_NAME="Presley" PHONE="+972123456789" EMAIL="elvis@isep.com" CREATION_DATE="2017-08-29"/>
    <CONSUMER CONSUMER_ID="2" FIRST_NAME="Bob" LAST_NAME="Dylan" PHONE="+972123456780" EMAIL="bob@isep.com" CREATION_DATE="2017-08-29"/>
    <CONSUMER CONSUMER_ID="3" FIRST_NAME="Lady" LAST_NAME="Gaga" PHONE="+972123456781" EMAIL="gaga@isep.com" CREATION_DATE="2017-08-29"/>
    </dataset>
    
  2. 或者我应该将其自动化吗?例如:

    @Test
    public void findByPhone(){
        ConsumerEntity consumerEntity = ConsumerUtil.createRandomConsumer();
        ConsumerEntity savedConsumerEntity = consumerRepository.save(consumerEntity);
        assertThat(consumerRepository.findByPhone(savedConsumerEntity.getPhone()).isEqualTo(savedConsumerEntity.getPhone());
    }
    

    我的createRandomConsumer生成随机数据。

    优点: 我认为自动化将更加通用和方便,就像ConsumerEntity可能会改变或接下来任何代码更改一样 - 我不必更改我的.xml文件,只是能够向TestEntity函数添加内容。 缺点: 如果在DB方案中包含任何约束,则创建新对象并保存到内存数据库可能会更加困难。

    1. 我应该使用DBUnit吗?如果自动化 - 我为什么要使用DBUnit?是否更好地使用JUnit(在每次测试后回滚数据,只是自动添加测试所需的数据,如上例所示?)

    2. 如果选择使用DBUnit - 并手动添加 - 这样的东西有什么好处?为什么它比使用简单的JUnit和Spring更好?

    3. 谢谢!

2 个答案:

答案 0 :(得分:1)

1)使用随机或运行时生成的夹具进行测试并不合适 它不会使测试具有可重复性,因此如果失败则使它们更难调试,并且它也不会使测试记录代码。

此外,具有明确数据的灯具可减少因数据生成而引起的副作用 您确定生成的数据符合要求吗?
您确定您的生成工具按预期工作吗? 你测试过了吗? 所以...... 找到所需的边缘情况很好,但发明不需要的边缘情况意味着您的测试将改变您的要求 你不希望这样。
如果您确定了所有特定情况并且想要生成一些数据,因为您认为组合太多(例如十几个输入案例),那么当然依靠要求生成夹具很好。
否则,不要因为它似乎是开销而使它。

2)DBUnit,这是一个选择 在我使用之前。现在,我停了下来。它有一些优点,但它很麻烦,维护/改进很轻 最近,我尝试了JBNizet的DbSetup(SO成员) 从Java代码中将数据插入数据库是一个很好的API:简单直接可用。

例如,要在数据库中插入数据,可以将Operation定义为:

Operation consumerInserts = sequenceOf(
    insertInto("CONSUMER")
        .columns("ID", "FIRST_NAME", "LAST_NAME")
        .values(1, "Elvis", "Presley")
        .values(2, "Lady", "Gaga")
        .values(3, "Bob", "Dylan")
        .build();
)

3)所以,没有什么可补充的。

答案 1 :(得分:1)

您似乎在问两个问题:是否使用DBUnit以及是否使用随机化。

至于DBUnit

  • 它增加了额外的步骤和额外的维护成本。如果您已经有代码来保存实体(通过XxxRepository),那么没有理由引入其他工具。
  • 这不仅适用于DBUnit,也适用于任何复制现有持久性逻辑的工具。
  • 相反,您只需创建一个对象实例,填充所有字段并保存到存储库。这使得重构变得更加容易。

至于测试随机化

  • 我认为你的测试看起来非常好。通过随机化,您可以用更少的测试覆盖更多案例,找到您无法想到自己的棘手案例,轻松隔离您的测试(例如,生成唯一的用户名,而不是在某处跟踪它们),等等。
  • 根据缺点:良好的随机性(以及一般的良好测试)需要良好的OOP命令,因此当项目变大时,并非每个人都可以轻松使用它。此外,测试开始失败,因为它们是匆忙写的,并不是每种可能性都被考虑在内。要捕获这种情况,你应该多次在本地运行测试(有时人们会忘记)。好消息:IntelliJ可以为JUnit重复测试N次(对于TestNG,有一个注释)。

一般来说,在编写随机测试时应该多考虑一下。但如果写得恰到好处,它们可以提供更好的覆盖范如果您对不同的随机化技术感兴趣,check this out