我正在进行一个使用Linq2SQL进行数据访问的项目。该项目由一个ASP.NET MVC应用程序和8个类库组成。大多数类库都有自己的L2S数据类。
作为我正在做的工作的一部分,我正在尝试测试各种组件,以引入一些稳定性。清理代码库,它目前大量使用静态类和方法,控制器具有贯穿始终的静态DataContext。
如何重构L2S的使用,以便测试控制器的操作?
我已经在应用程序中引入了依赖注入,以解耦其他一些服务,但我不希望DataContext作为控制器的依赖属性,因为我想控制DataContext及其DataLoadOptions的实例化。
我尝试过的一件事是利用L2S生成的分部类,并向DataContexts添加了一个Interface,但我发现抽象会一直渗透到应用程序中,而不是停留在类库中。这感觉不像是正确的做事方式,维持下去会很痛苦。有人用这种方法取得过特别的成功或失败吗?
我使用Repository模式将DataContext
隐藏在里面。存储库是抽象的,所以套件非常适合使用依赖注入原理。
例如,您定义了一些存储库。
public interface IUserRepository
{
User Get(int id);
User Save(User user);
void Delete(User user);
}
实现有点像
public class UserRepository : IUserRepository
{
private MyDataContext _context;
UserRepository()
{
_context = new MyDataContext();
}
// ...
}
现在,控制器只依赖于接口。
public UserController : Controller
{
UserController(IUserRepository userRepository) { }
}
因此,它是完全可测试的,因为您可以在测试中模拟IUserRepository
。
虽然本文提到了使用实体框架的可测试性,但这里可以应用高级概念。
示例的核心概述了使用"工作单元"模式和"存储库"模式。工作单元是围绕数据上下文的抽象,代表特定控制器或类似控制器的工作集。您可以在单元中包括多个存储库,并且由于存储库基于IEnumerable
或IQueryable
,因此您仍然可以利用LINQ功能。
可测试性选项包括模拟单元和存储库,或在内存中创建用于测试的表示。