是否应该模拟数据库连接?

时间:2015-01-01 22:42:37

标签: database testing mocking

我正在尝试将单元测试应用于我正在进行的项目中。我使用Python和MySQLdb,但我认为这个讨论与语言无关。 我想测试一个函数,让我们称之为foobar()。它执行类似于以下的SQL查询:

cursor.execute("SELECT * FROM my_table WHERE a == " +varA+ " AND  b < " +varB)

这个功能有一点复杂性。 cursor.execute(query)被调用的频率和频率取决于foobar的论点。

现在我不确定是否应该模拟数据库连接cursor。 如果我不这样做,那就太糟糕了,因为测试取决于数据库服务器的可用性。 如果我这样做,那很糟糕,因为模拟必须知道将调用哪些查询。但确切的查询是一个实现细节。例如。查询是以小写还是大写编写,不会影响foobar的正确性。但改变这一点将打破考验。由于模拟对象有点复杂,测试也很难阅读。

这是选择较小的邪恶的情况吗?还有第三种方式吗?

2 个答案:

答案 0 :(得分:0)

您已经在权衡利弊方面做得很好,但有一点需要注意的是,测试的目的是模拟接近生产中可见的确切条件。

您应该避免模拟数据库连接,并让它从本地MysQL数据库实例读取。此外,确保在每次测试之前重置db的状态以确保测试模块化。

一般工作流程是 -

  1. 在所有测试之前创建架构myApp_test,如果它尚未存在。
  2. 删除所有表并从模拟数据夹具重新创建它们。您可以通过多种方式执行此操作,我最喜欢的是从YML配置文件中读取fixture并将它们直接插入到DB中。 (如果您正在使用像rails这样的框架,它具有预先构建的功能,或者有许多其他语言的宝石和库可能对此有所帮助。)
  3. 在每次测试之前,请调用步骤2中的功能以重置数据库
  4. 运行测试
  5. 为了回应您的担忧,我不认为这取决于数据库是否可用,特别是在本地。如果您正在运行测试,那么指定您应该有可用的数据库并非没有道理。或者,如果您真的关心数据库可用性,可以尝试使用SQLite或其他基于文本的本地数据库在本地创建自己的数据库

答案 1 :(得分:0)

不,你不应该模仿光标或连接。重构代码并将此代码提取到单独的服务/存储库。应该有一个方法,它接受两个参数varAvarB并返回行/对象列表

  • 在您的快速/单元测试中,您应该模拟整个存储库 - 检查您的方法是否使用适当的参数调用(varAvarB)。
  • 在慢速/集成测试中,您应该检查您的真实数据库是否正确执行了此查询以查找所有可能的varAvarB

通过模拟连接/光标,你只需要实现数据库 - 这只是浪费时间