Java 单元测试如何在spring中插入记录(无删除方法)

Java 单元测试如何在spring中插入记录(无删除方法),java,spring,unit-testing,dao,jdbctemplate,Java,Spring,Unit Testing,Dao,Jdbctemplate,我让DAO使用Spring的jdbcTemplate和CREATEREADUPDATE(无删除)操作 Create方法的ID参数是表中唯一的键 除了模拟DAO,我如何在不违反约束的情况下实际测试create 使用随机ID有时仍然会失败 我是否应该覆盖setAutoCommit以避免添加记录?它仍然是一个有效的单元测试吗? 我必须事先在SQL中删除数据库中的记录,或者对于这种类型的测试是否有spring选项 或者应该把它看作是集成测试而不是单元测试?< /P> 编辑 我使用的是Oracle,无法使

我让DAO使用Spring的
jdbcTemplate
和CREATEREADUPDATE(无删除)操作

Create方法的ID参数是表中唯一的键

除了模拟DAO,我如何在不违反约束的情况下实际测试create

使用随机ID有时仍然会失败

我是否应该覆盖setAutoCommit以避免添加记录?它仍然是一个有效的单元测试吗?

我必须事先在SQL中删除数据库中的记录,或者对于这种类型的测试是否有spring选项

或者应该把它看作是集成测试而不是单元测试?< /P> 编辑

我使用的是Oracle,无法使用sequence为ID创建值


我们在生产中有一些数据源(不用于测试)

这实际上取决于此类测试的目的,并非所有测试都是这方面的“单元测试”

例如,如果目标是测试封装业务逻辑的“服务”,但是从这个服务中,有时会调用DAO,那么最好的方法可能就是按照您的建议模拟DAO。 在这种情况下,DAO显然不在本测试的范围内,但服务会

如果目的是测试SQL语句(我假设DAO只包含SQL语句+可能将它们转换为域对象),那么模拟就不是一个选项

在这种情况下,测试应该包括对某种数据库的调用,但在这种情况下,它不再称为单元测试(单元测试是运行非常快的东西,只在内存中运行,没有DBs,没有I/O等)。我将此称为集成测试(正如您所建议的),但是不同的人对这种测试可能有不同的名字

实际上,我们需要两种测试,因为它们测试不同的东西

那么,如何测试这个呢

首先,应做出决定,应使用哪个数据库,这里有3种方法:

  • 运行一个真实的数据库,在用户之间共享,测试假定它是预安装的
  • 使用内存中的数据库运行
  • 在测试套件运行时运行DB的DB docker映像,然后销毁它
  • 虽然关于哪种方法更好的讨论本身非常有趣,但在我看来,这超出了这个问题的范围,每种选择都有其影响

    完成此决定后,应该从代码中决定如何使用此数据库

    弹簧测试通常使用以下模式:

  • 在测试之前打开一个事务
  • 运行测试(更改数据,甚至更改模式-如果需要,可以添加列和表)。做断言
  • 不管测试结果如何,回滚事务,使数据与测试前一样
  • 因此,如果您对所有测试都采用这种方法,那么它们将以“空”数据状态开始,这样就不会出现违反约束的情况 这也有效地解决了“删除记录”问题,因为在回滚事务时,数据将被删除

    现在,关于删除交易之外的记录

    一种明显的方法是从测试中执行删除sql(在DAO之外),这样DAO(生产代码不会被更改)


    您可以将DataSource/JDBCTemplate直接注入测试(Spring测试完全支持这一点)并从中调用所需的SQL

    I have autoCommit=true且生产中很少有数据源,您是否建议特定测试在测试中注入特定数据源并手动回滚?为testsspring测试框架维护不同的数据源似乎会增加开销。Spring测试框架为您配置所有内容,如果您将@Transactional置于测试状态,它将回滚事务。关于生产中的多个数据源。您是否在生产数据库上运行测试?不,它是在测试环境中执行的。我认为您不需要特殊的数据源。如果autoCommit=true,则保持如下状态。Spring测试框架只是在测试之前打开一个特殊的测试事务,以便在测试内部创建的任何事务都只加入“外部”事务,并且只有测试之后的回滚才会实际更改数据库(回滚)