我应该对数据访问层进行单元测试吗?这是一个好习惯以及如何去做?
Posted
技术标签:
【中文标题】我应该对数据访问层进行单元测试吗?这是一个好习惯以及如何去做?【英文标题】:Should I Unit Test Data Access Layer? Is this a good practice and how to do it? 【发布时间】:2011-03-20 23:22:00 【问题描述】:如果我有数据访问层 (nHibernate),例如一个名为 UserProvider 的类 和一个业务逻辑类 UserBl,我应该同时测试他们的方法 SaveUser 或 GetUserById,还是 DA 层中从 BL 层调用的任何其他公共方法。这是一种冗余还是一种常见做法?
单元测试DA层是通用的还是属于集成测试域的? 有测试数据库更好,还是在测试过程中创建数据库数据?
感谢任何帮助。
【问题讨论】:
【参考方案1】:最好为每一层编写单元测试,甚至是 DAL。
我认为在真实数据库上运行测试不是一个好主意,您可能会破坏重要数据。我们曾经为测试设置一个数据库副本,其中包含足够的数据来运行测试。 在我们的测试项目中,我们有一个特殊的 web.config 文件,其中包含测试设置,例如连接到我们的测试数据库的 ConnectionString。
【讨论】:
【参考方案2】:对此没有正确答案,这真的取决于。有些人(例如Roy Osherove)说您应该只测试具有条件逻辑(IF 语句等)的代码,这可能包括也可能不包括您的 DAL。有些人(通常是从事 TDD 的人)会说您应该测试所有内容,包括 DAL,并以 100% 的代码覆盖率为目标。
就我个人而言,我只测试它是否包含逻辑,因此最终会测试一些 DAL 方法,而另一些则没有。大多数情况下,您最终只是检查您的 BL 是否调用了您的 DAL,这有一些优点,但我认为没有必要。我认为进行端到端覆盖应用程序的集成测试更有意义,包括涵盖 GetUserById 等内容的数据库。
无论哪种方式,您可能已经知道这一点,但请确保您的单元测试不会触及实际的数据库。 (这样做没问题,但这是一个集成测试而不是单元测试,因为它需要更长的时间并且涉及复杂的设置,并且应该单独运行)。
【讨论】:
这与我对 DAL 测试的看法非常相似。如果那里有任何逻辑并且您想确保它有效,请为其编写单元测试。总体而言,最好的时间和精力可能是针对具有已知测试数据的真实数据库设置集成测试。 而SQL不包含逻辑? @Pascal - 我的 SQL 通常不会,不,但我并不是说你不应该测试它。但我不会将它作为 DAL 的一部分进行测试,它要么是一组单独的单元测试(可能使用不同的工具,也许是 DBFit),要么是集成测试的一部分。正如我所说,由于设置的复杂性、潜在的环境问题(需要本地数据库或网络)以及速度降低,我认为“代码”单元测试不应触及数据库。【参考方案3】:根据我的经验,单独测试每一层很有帮助。集成它并再次测试。集成测试通常不会测试所有方面。有时,如果数据访问层(我不知道 nHibernate)是生成代码或某种通用代码,它看起来有点矫枉过正。但我不止一次地看到,系统测试是有回报的。
是冗余吗?在我看来不是。
这是常见的做法吗?很难说。我会说不。我在一些项目中看到过,但不是在我参与的所有项目中都看到过。通常取决于团队/个人开发人员的时间/资源和心态。
有测试数据库更好,还是在测试期间创建数据库数据?这是一个完全不同的问题。不能轻易回答。取决于你的项目。创建一个新的很好,但有时会抛出不真实的错误(尽管错误)。这取决于您的项目(产品开发或专有开发)。通常在专有的现场开发中,数据库会从某个地方迁移到其中。因此,迁移的数据肯定需要进行第二次测试。但这只是在系统测试级别。
【讨论】:
【参考方案4】:单元测试 DAL 是值得的,如前所述,如果其中有逻辑,例如,如果使用相同的 StoredProc 进行插入和更新,则值得知道插入有效,随后的调用会更新先前的调用,然后选择返回它并且不是列表。在您的情况下,SaveUser 方法可能会在第一次插入并随后更新,很高兴知道这是在单元测试阶段所做的事情。
如果您使用 iBatis 或 Hibernate 之类的框架,您可以在其中实现类型处理程序,则值得确认处理程序以您的底层数据库可接受的方式处理值。
至于测试实际数据库,如果您使用像 Spring 这样的框架,您可以利用支持的数据库单元测试类和事务的自动回滚,这样您就可以运行测试并且之后数据库不受影响。有关信息,请参阅here。其他人可能会提供类似的支持。
【讨论】:
以上是关于我应该对数据访问层进行单元测试吗?这是一个好习惯以及如何去做?的主要内容,如果未能解决你的问题,请参考以下文章