【发布时间】:2011-06-05 20:03:51
【问题描述】:
考虑存储库模式(或类似模式)的实现。我会尽量保持示例/插图简洁:
interface IRepository<T>
{
void Add(T entity);
}
public class Repository<T> : IRepository<T>
{
public void Add(T entity)
{
// Some logic to add the entity to the repository here.
}
}
在这个特定的实现中,Repository 由接口 IRepository 定义,以具有一个将实体添加到存储库的方法,从而使 Repository 依赖于泛型类型 T(此外,Repository 必须隐式依赖于另一种类型 TDataAccessLayer ,因为抽象是存储库模式的全部要点。但是,这种依赖关系目前还不容易获得)。在这一点上,据我目前的理解,我有两个选择:单元测试和集成测试。
如果假设集成测试有更多的活动部件,我宁愿最初进行单元测试,以便至少验证基线功能。但是,如果不创建某种“实体”属性(泛型类型 T),我无法断言任何逻辑实际上是在 Repository 实现的 Add() 方法中执行的。
是否存在单元测试和集成测试之间的中间地带,它允许(通过反射或其他方式)验证在测试单元中是否已达到特定的执行点?
我对这个特定问题的唯一解释是从存储库中进一步抽象数据访问层,导致 Add() 方法不仅接受实体参数,还接受数据访问参数。但是,在我看来,这可能会破坏存储库模式的目的,因为存储库的使用者现在必须知道数据访问层。
关于请求示例:
(1) 关于单元测试,根据我对当前测试技术的理解,我不确定像存储库这样的东西实际上是否可以进行单元测试。因为存储库是围绕特定数据访问层的抽象(包装器),所以似乎唯一的验证方法是集成测试? (当然,存储库接口可能不绑定到任何特定的 DAL,但任何实现的存储库肯定必须绑定到特定的 DAL 实现,因此需要能够测试 Add() 方法是否实际执行了一些工作)。
(2) 关于集成测试,据我了解该技术,测试将通过实际调用 Add() 方法(应该向存储库添加一条记录)来验证 Add() 方法是否执行工作,并且然后检查数据是否实际添加到存储库(或者可能是特定场景中的数据库)。这可能看起来像:
[TestMethod]
public void Add()
{
Repository<Int32> repository = new Repository<Int32>();
Int32 testData = 10;
repository.Add(testData);
// Intended to illustrate the point succinctly. Perhaps the repository Get() method would not
// be called (and a DBCommand unrelated to the repository issued instead). However, assuming the
// Get() method to have been previously verified, this could work.
Assert.IsTrue(testData == repository.Get(testData));
}
因此,在这种情况下,假设存储库是某个数据库逻辑层的包装器,那么数据库实际上会在测试期间被命中两次(一次在插入期间,一次在检索期间)。
现在,我认为有用的是一种技术,用于验证在运行时是否采用了特定的执行路径。例如,如果传入的是非空引用,则采用验证执行路径 A,如果传入的是空引用,则采用验证执行路径 B。此外,也许可以验证要执行特定的 LINQ 查询。因此,在测试期间数据库从未真正受到影响(允许在没有任何实际 DAL 的情况下进行原型设计和开发)。
【问题讨论】:
-
你在这里究竟在哪里划定“单元测试”和“集成测试”之间的界限?假设您想对“添加”方法进行单元测试 - 您能举个例子,单元测试应该是什么样子,集成测试应该如何不同于那个?
-
你到底想测试什么?具体实现?遵循一条思路:如果您使用的是 TDD,那么如果没有单元测试,您就不会拥有具体的实现。因此,问自己希望实现实现哪些功能就等于问自己希望它通过哪些测试。
-
@John Saunders 在某种程度上,我同意你所说的关于 TDD 的看法。我添加了更多信息,希望能更好地定义问题。我只是不确定目前是否可以通过单元测试来驱动诸如存储库之类的开发。
-
@Brad:我会看看你的方法,但仅供参考,我发现很少有不能通过 TDD 创建的。
-
@John Saunders 这可能只是我缺乏理解。我只是还没有看到一种方法来执行我尝试执行的各种测试而不实际运行集成测试。
标签: c# unit-testing integration-testing