C# · 2月 19, 2022

c# – 存在中间地带吗? (单元测试与集成测试)

考虑存储库模式(或类似)的实现.我会尽量保持示例/插图的简洁:

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)关于单元测试,我不确定像我的对当前测试技术的理解,实际上可以对存储库进行单元测试.因为Repository是围绕特定数据访问层的抽象(包装器),所以似乎唯一的验证方法是集成测试? (当然,存储库接口可能不会绑定到任何特定的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的情况下进行原型设计和开发).

解决方法 听起来您正在描述实现细节的测试,而不是模式的实现者满足模式的要求.如果在测试单元内达到“特定执行点”并不重要,只有具体实现者维护接口合同才有意义.测试创建一个T实体用于测试目的是完全可以接受的,这就是模拟的目的.