Database 如何在不影响数据库的情况下测试服务?
我正在为Spring中的应用程序编写一些集成测试。我想测试一些服务,但它们可能会调用一些数据访问对象,新数据将保存在我的数据库中。在测试完成后,我有两种方法可以清除数据库中的每一项内容:Database 如何在不影响数据库的情况下测试服务?,database,spring,testing,rollback,Database,Spring,Testing,Rollback,我正在为Spring中的应用程序编写一些集成测试。我想测试一些服务,但它们可能会调用一些数据访问对象,新数据将保存在我的数据库中。在测试完成后,我有两种方法可以清除数据库中的每一项内容: 使用临时数据库在那里插入测试数据 每次我做测试都要清理所有的表格 然而,我正在寻找一种干净、向前的方法,这样我就可以不用手动清理就可以使用我的数据库。有什么想法吗 还有另一种选择:在测试服务时,对DAO使用mock 单元测试不同于集成测试。单元测试应该只关注感兴趣的类,而不是它的所有依赖项 我假设您已经以事务方
然而,我正在寻找一种干净、向前的方法,这样我就可以不用手动清理就可以使用我的数据库。有什么想法吗 还有另一种选择:在测试服务时,对DAO使用mock 单元测试不同于集成测试。单元测试应该只关注感兴趣的类,而不是它的所有依赖项 我假设您已经以事务方式对DAO进行了单元测试,因此无需再次证明它们工作正常 您没有提到的集成测试的另一个选项是使来自服务的所有数据库交互都是事务性的。执行这些操作,完成后将其回滚
临时数据库是一个很有吸引力的选择。您可以使用一些小而轻的东西,如高超音速、德比或SQLLite。缺点是您必须更新模式两次:一次在测试数据库中,一次在生产实例中。无论如何,如果你必须这样做,那就太糟糕了。对问题的评论做出回答,因为仅仅一条评论无法捕捉到它 在每次测试之间建立和拆除数据库对于性能来说无疑是非常昂贵的。如何进行完全取决于数据库本身。(mssql、MySQL、PostgreSQL等)如果您可以在使用相同代码的情况下交换一个完全在内存中的数据库,那么这将是每次测试中设置和拆除的最快的数据库 例如,我曾经有一个项目,需要对MS SQL实例运行测试。安装和拆卸大大降低了测试的速度,但我们都认为扩展测试覆盖范围是值得的。(我们每晚运行集成测试,而不是在签入时运行,所以这也没什么大不了的。)为了完全刷新数据库,我们使用了以下代码(C#,抱歉): 然后在测试的配置中,我们有三个值:
DataResetter
的接口。然后每个数据访问实现(SQL、内存中、XML)都实现了该接口。SQL使用上述代码和配置值,内存中的只清除了静态列表,XML的只删除了XML文件
这允许测试将域功能用于测试设置和拆卸,并允许依赖项注入容器确定要使用的实现。这样,测试就不会与任何特定的实现耦合。这样做的另一个好处是,相同的测试可以用于单元和集成目的它们之间的区别只不过是一个配置设置
(首先测试整个域是否与内存中的模拟实现一起工作,然后使用一个依赖项实现再次测试域,再使用另一个实现再次测试域,等等。我们最终在整个系统中为十几个不同的依赖项实现每晚运行同一组测试十几次。一次一个依赖项。这让我们很容易地看到什么东西坏了,因为在任何给定的测试运行中,只有一个新变量。)还有另一个选项:事务回滚
根据您打开和提交事务的方式,您可能不提交事务,而是返回角色。如果您使用的是Spring框架,那么我认为您应该已经检查了Spring的测试方法。 您将看到Spring将使它变得如此简单,您不需要直接与事务交互。您只需要在测试顶部添加一个@Transactionl注释,那么使测试具有事务性有什么好处呢?是的!正如前面其他答案所述,它将允许您回滚您的事务sactions,因此数据库中不会保留任何内容。请查看以下示例代码:
@Transactional
public class FictitiousTransactionalTest {
@Before
public void setUpTestDataWithinTransaction() {
// set up test data within the transaction
}
@Test
@Rollback(true)
public void modifyDatabaseWithinTransaction() {
// logic which uses the test data and modifies database state
}
}
我需要注意一些重要的事情
@Transactional
public class FictitiousTransactionalTest {
@Before
public void setUpTestDataWithinTransaction() {
// set up test data within the transaction
}
@Test
@Rollback(true)
public void modifyDatabaseWithinTransaction() {
// logic which uses the test data and modifies database state
}
}