【问题标题】:Best approach for unit testing with data使用数据进行单元测试的最佳方法
【发布时间】:2017-05-22 14:43:29
【问题描述】:

我有很多 DAO 类需要在 Spring 项目中进行测试。

我已经在使用 DBUnit 来模拟我的数据库,但是我使用 @Before 注释来创建对象并在对创建/更新/删除操作进行测试之后比较它们。

@DatabaseSetup(value = { "/db_data/dao/common.xml", "/db_data/dao/myDAOCommonTest.xml" })
@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
public class MyDAOImplTest extends AbstractDaoTU {

  @Autowired
    private MyDAO myDAO;

    private Set<ClassNeeded> objectsNeeded = new HashSet<>();
    private ClassOne classOne;
    private ClassTwo classTwo;

    private ClassThree classThree;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        this.objectsNeeded.add(somethingComingFromTheMotherClass);

        this.classOne = new ClassOne();
        this.classOne.setIdClassOne(1L)
    this.classOne.setObjectsNeeded(this.objectsNeeded);
        // ... Many other sets

        this.classTwo = new ClassTwo();
        this.classTwo.setIdClassTwo(1L);
    this.classTwo.setClassOne(this.classOne);
    // ... Many other sets

    // ... Other sets follow for a lot of other objects
    }

  @Test
  public void testOne {
    // ...
  }

  // ... Other tests follow
}

我正在使用 ORM(在这种情况下为 Hibernate),并且大多数对象是相互依赖的。我的 dao 函数大多需要完整的对象才能被调用,所以我必须在测试之前创建对象。

我的问题如下:

  • 是否有更好的方法来对 DAO 进行单元测试?
  • 您知道哪些工具可以使编写更容易/更快? (我使用maven进行打包)

感谢您的帮助!

【问题讨论】:

  • 这不完全是问题,但确实是一个好点。我有时会根据非常具体的需要更改测试中的一些对象属性值,所以我不使用@BeforeClass。这是一个不好的做法吗?我想无论如何我都会调查它,并移动在 BeforeClass 方法中会更好的对象。感谢您的建议。
  • 哦,好吧,我想我们误会了。我的意思是写得更快。我知道BeforeClass。由于这是我加入的一个大项目,我尝试遵循我之前使用的做法。不过,我确信这不是一个坏习惯,但我会尝试使用它。再次感谢。

标签: java hibernate unit-testing junit


【解决方案1】:
  1. 数据库单元使测试的维护变得复杂,因为它增加了在发生变化时需要更新的地方的数量。此外,它过多地将数据准备与测试分开,因此很难找到哪些数据与哪些测试相关。
  2. 理想情况下,每个测试都为自己准备数据。这会移除全局状态并将相关事物保持在一起。

要准备数据,只需创建实体并将它们保存在同一个测试中。您可以使用随机化和事务回滚来隔离测试。这是我的一个项目中的一个示例:

@Test public void returnsExperimentAsItWasSaved() {
    Experiment original = Experiment.random();
    experimentRepository.save(original);
    flushToDbAndClearCache();

    Experiment fromDb = experimentRepository.findOne(original.getExperimentId());
    assertReflectionEquals(original, fromDb);
}

注意,相同的 DAO 类用于准备数据。

【讨论】:

  • 您的意思是使用实体管理器(我知道 Jhipster 框架在其测试中使用这种东西)?每个测试共有的数据是否仍应在 @before 中初始化?还是不够可读?
  • 当您进行 10-20 次测试时,@Before 中的内容非常不可读,因为您必须在那里准备完全不相关的对象。您可以使用相同的 DAO 类来准备数据(更新了我的答案)。
  • 好的,那我试试。谢谢!
【解决方案2】:

最好的方法是像开发代码一样开发测试:重构以尽量减少重复、提取可重用服务等。

因此,您可能会创建一些 TestCaseFactory 链接一整套对象并使用您的实际 DAO 保存它们。然后,您可以像以前一样从@Before 调用它们。如果你需要很多不同的对象集,你可以创建不同的方法或参数对象等。

并清理@After 中的所有测试数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2019-02-12
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    相关资源
    最近更新 更多