通过模拟数据层或使用嵌入式数据库进行单元测试

时间:2012-07-18 21:22:57

标签: java unit-testing derby easymock

对于单元测试,最好是模拟数据层还是使用像derby这样的嵌入式数据库?

我知道这也取决于测试的目的。但如果我去德比,我不必模仿所有的对象,我认为这会更容易。另一方面,我理解这更倾向于集成测试。那么哪一个更常见于单元测试?

感谢。

根据评论更新:

所以我现在配置了德比,但我的经理坚持使用easymock。我们正在使用jpa,我们有大约20个表=>数据模型。那么对于像项目模型这样的每个方法,我应该为其所有方法指定mockedProject的返回类型吗?像getProjectName(),getProjectId()等?我也应该模拟持久性管理器对象。我认为与仅仅配置像derby这样的嵌入式数据库相比,这只是很多。

3 个答案:

答案 0 :(得分:2)

对于单元测试,我建议模拟您的数据层。这清楚地表明您没有测试数据层的功能,也增加了单元测试的速度。

在进行集成测试时,您应该有一个连接到数据层的实时数据库,我更喜欢使用与生产中使用的相同类型的数据库来限制稍后引入新错误的风险。另外,我建议让每个测试都构建自己的测试数据,然后将其删除,因为这样可以确保每个测试都不受其他测试用例中与测试数据交互的影响。

答案 1 :(得分:2)

首先,如果在单元测试中使用外部组件(如数据库,文件系统等),则不能再称为单元测试,而是集成测试代替。

另一方面引用经典Mocks Aren't Stubs说:

  
      
  • 对象实际上有工作实现,但通常需要一些使它们不适合生产的快捷方式(内存数据库就是一个很好的例子)。
  •   

在单元测试中使用假货并没有错。

话虽如此,我建议使用一些快速简单的内存数据库,如。嘲弄DataSourceConnectionResultSetPreparedStatement ......不值得痛苦。

另见

答案 2 :(得分:1)

如果你正在使用JPA,你不需要模拟你的Project对象,因为它们可能只是愚蠢的POJO,对吧?你需要模拟的只是持久性管理器对象(EntityManager)。在最简单的情况下(如果您使用Mockito或Easymock与'niceMock'),您可能只需要创建模拟并注入它,就是这样。根据您正在测试的内容,您可能希望执行更多操作:验证是否调用了savemerge方法,指定它将在{{上返回特定的Project对象1}}打电话等。

模拟EntityManager有几个好处:

  1. 它运行速度非常快 - 比嵌入式数据库快得多。这些测试将会运行很多次,所以重要的是它们不会有太大的负担。
  2. 您无需填充真实数据库。虽然您可能需要对某些集成测试执行此操作,但很难找到涵盖所需方案的数据库。通过模拟,您可以在测试中创建您想要的特定场景。
  3. 您可能希望测试实际上很难实现的某些条件,例如IO错误或数据库中已存在但违反某些约束的数据。通过模拟,您只需告诉模拟器在调用方法时抛出异常。连接到真实的数据库(甚至嵌入式),要实现这一目标将非常困难(如果不是不可能的话)。
  4. 嘲笑POJO没有这些好处。执行POJO的代码与模拟POJO一样快。填充POJO可能有点痛苦,但不如设置模拟POJO的行为那么多。而且由于POJO不会(通常)对外部依赖性有很大影响,因此很少需要第三个好处。