【问题标题】:Unit test: Real database vs. mocking单元测试:真实数据库与模拟
【发布时间】:2013-03-15 12:42:40
【问题描述】:

我正在对我们团队正在构建的 asp.net MVC 3 Web 应用程序进行单元测试。

问题是我们必须模拟很多东西,而我们的单元测试并没有涵盖所有与网络服务器和数据库相关的东西。

例子:

我有一个方法,代码如下:

public List<Useraccount> GetUseraccounts(Company company)
{
    return company.Useraccounts.ToList<Useraccount>();
}

我的开发人员抱怨他必须注入一个他自己准备的假公司对象。他想从数据库中获得一个真实的对象。

我的问题: 是否可以在单元测试中使用真正的数据库(也可以是 SQLite/SQLExpress 或其他东西)?这有用吗? 有什么好处和坏处?

如果没有真正的数据库,我们需要模拟太多的对象。例如,我们无法验证此类调用是否有效:

Useraccount useraccount = UnitOfWork.UseraccountRepository.Get(u => u.EnableCode == enableCode && u.IsEnabled == false).Single<Useraccount>();

【问题讨论】:

  • 听起来你可能会模糊 unit 测试和 integration 测试之间的界限。
  • 什么意思?真正的数据库内容仅用于集成测试?
  • 我相信@Forty-Two 的意思是你应该考虑两套测试。一个是关于单元测试,测试你的类做他们应该做的事情和模拟依赖关系。然后,您可以进入下一个级别的黑盒/集成测试,您可以在其中全面测试您的服务,但在需要时模拟第三方服务。
  • 是的,但我实际上无法测试像 Useraccount useraccount = UnitOfWork.UseraccountRepository.Get(u => u.EnableCode == enableCode && u.IsEnabled == false).Single 这样的方法。用户帐户>();因为 EF。

标签: asp.net asp.net-mvc entity-framework unit-testing moq


【解决方案1】:

针对真实数据库的测试是集成测试,而不是单元测试。您仍然可以以与单元测试相同的方式运行集成测试 - 也就是说,通过 nunit 或 mstest 或其他方式运行它们,并通过构建服务器上的命令行或类似方式运行它们 - 但还有一些额外的步骤:

  1. 您需要设置测试数据,将其注入数据库,运行测试,然后再次删除测试数据。在理想情况下,您会在集成测试运行开始时创建一个测试数据库,然后运行所有测试,然后在所有集成测试完成后将其删除。不过,这可能是不切实际的。

  2. 您的集成测试将比单元测试运行得慢得多。为此做好准备,例如在构建服务器作业中每晚运行它们。

在使用 SqlLite 或其他方面,我会说不要使用您在现实世界中使用的确切类型的数据库,否则它不是一个值得信赖的测试。

【讨论】:

  • 感谢您的回答。基本上我们首先想“完成”单元测试。我的感觉是它们不完整,因为我们无法在代码中测试很多行,因为实体框架。
  • 我会说这是一个罕见的应用程序,它可以仅使用单元测试来覆盖所有(甚至大部分)数据访问代码行。话虽如此,您确定 EF 是问题所在,并且代码不能被重新设计以提高单元测试的可测试性吗?
【解决方案2】:

尝试使用Effort 工具。 Effort 是一个强大的工具,它可以方便地为基于实体框架的应用程序创建自动化测试。 它基本上是一个 ADO.NET 提供程序,它在轻量级进程内主内存数据库而不是传统的外部数据库上执行所有数据操作。它还提供了一些直观的帮助方法,可以很容易地将此​​提供程序与现有的 ObjectContext 或 DbContext 类一起使用。对现有代码的简单添加可能足以创建可以在没有外部数据库存在的情况下运行的数据驱动测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    相关资源
    最近更新 更多