【发布时间】:2011-11-11 23:44:54
【问题描述】:
在 TDD 中,我一直在通过模拟数据访问功能来测试业务逻辑。 但实际上我还需要实现业务层以下的层才能使应用程序正常工作。
我应该使用 TDD 实现数据访问层吗?
根据我在网络上看到的讨论,单元测试不应该连接到任何外部资源,如数据库、网络服务等。如果它们连接,那么它们就成为集成测试。
请有人对此有所了解。
非常感谢。
【问题讨论】:
标签: tdd data-access-layer
在 TDD 中,我一直在通过模拟数据访问功能来测试业务逻辑。 但实际上我还需要实现业务层以下的层才能使应用程序正常工作。
我应该使用 TDD 实现数据访问层吗?
根据我在网络上看到的讨论,单元测试不应该连接到任何外部资源,如数据库、网络服务等。如果它们连接,那么它们就成为集成测试。
请有人对此有所了解。
非常感谢。
【问题讨论】:
标签: tdd data-access-layer
您是对的,与外部的联系使其成为集成测试,但这种联系对于测试也很重要。使用 TDD,它应该暴露给你,接触面尽可能小。这可以通过对每条记录使用包装器或类似方法来实现。
【讨论】:
例如,如果您使用的是 Hibernate 之类的东西,并且如果您的 DAO 中有任何类型的逻辑,您可以模拟对会话和查询的调用以及单元测试,而无需访问数据库。
如果您想自己测试查询,可以使用内存数据库和 DbUnit 之类的东西。我会将这些视为集成测试并单独运行它们,因为它们往往需要更长的时间。
这是一个典型的 Java Spring/Hibernate DAO 方法示例,其中包含您可能想要测试的一些逻辑:
public List<Entity> searchEntities(final String searchText, final int maxResults) {
String sql = "select * from entity where field like :text";
Query query = sessionFactory.getCurrentSession().createSQLQuery(sql);
if (maxResults != 0) {
query.setMaxResults(maxResults);
}
query.setString("searchText", "%"+searchText+"%");
return query.list();
}
使用模拟框架,您可以模拟 sessionFactory、session 和 query,并创建一个单元测试,期望 query.setMaxResults 仅在不等于 0 且 query.setString 为用正确的字符串值调用。您还可以断言从 query.list() 返回的任何内容都是该方法返回的内容。
然而,这会让你测试代码与你的这个方法的实现相耦合。此外,如果您的 DAO 方法中包含大量逻辑,那么您应该考虑重构并将此逻辑移动到服务层,您可以在其中将其与任何数据库交互分开进行单元测试。
【讨论】:
您可以使用 Dev Magic Fake 来伪造 DAL,这样您就可以根据需要使用 TDD,而无需为 Fake DAL 编写任何代码
只需添加对 DevMagicFake.dll 的引用,您就可以编写以下代码:
[HttpPost]
public ActionResult Create(VendorForm vendorForm)
{
var repoistory = new FakeRepository<VendorForm>();
repoistory.Save(vendorForm);
return View("Page", repoistory.GetAll());
}
这会将 VendorForm 永久保存在内存中,您可以在需要时随时检索它,您还可以为此对象或模型中的任何其他对象生成数据,而无需为该操作编写任何代码,所以现在您可以在您已经完成 DAL 时制作 TDD 有关 Dev Magic Fake 的更多信息,请参阅 CodePlex 上的以下链接:
http://devmagicfake.codeplex.com
谢谢
M.拉德万
【讨论】: