考虑存储库模式(或类似)的实现。我会尽量保持示例/插图的简洁:
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()方法实际执行某些工作)。 / p>
(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的情况下进行原型设计和开发)。
答案 0 :(得分:2)
听起来您正在描述实现细节的测试,而不是模式的实现者满足模式的要求。如果在测试单元内达到“特定执行点”并不重要,只有具体实现者维护接口合同才有意义。测试创建一个T
实体用于测试目的是完全可以接受的,这就是模拟的目的。
答案 1 :(得分:0)
如果要进行集成测试,则需要使用真实数据库。但是如果你想快速测试一下你可以尝试一个内存数据库。 问题是你可以测试什么以及你无法测试什么。只要您的数据库访问代码是特定于数据库的,您就可以使用外部系统(保持单元测试说话),您应该模拟它。但是,既然您真的想知道数据是否最终存在于数据库中,则需要针对真实数据库进行测试。
但是如果你使用一些数据库抽象,例如ORM映射器,您可以使用ORM映射器并测试至少映射是否正常工作。然后,ORM映射器可以使用内存数据库进行测试,以检查ORM映射器是否按预期工作。
如果你不使用ORM映射器而你创建一个额外的数据库抽象层只是为了有一个抽象,所以你拥有的代码只是为了你想要在真正的单元测试中发现的错误而执行的为了提高你的工作效率。