Asp.Net MVC 5中IoC与依赖注入的控制器测试求助
如何给Asp.Net MVC5的WorkPlacesController.Index()注入依赖并获取真实数据库查询结果
刚接触MVC测试确实容易卡在依赖注入这一步,我来一步步帮你搞定——要让Index()方法返回真实数据库结果,核心就是把控制器依赖的所有服务、仓储、工厂都用真实的实现类实例化,并且连接到你的数据库。
第一步:先理清你的依赖链
首先得明确WorkPlacesController到底依赖了哪些东西。举个常见的例子,假设你的控制器构造函数是这样的:
public class WorkPlacesController : Controller { private readonly IWorkPlaceService _workPlaceService; public WorkPlacesController(IWorkPlaceService workPlaceService) { _workPlaceService = workPlaceService; } public ActionResult Index() { var workPlaces = _workPlaceService.GetAll(); return View(workPlaces); } }
那依赖链就是:WorkPlacesController → IWorkPlaceService → IWorkPlaceRepository → YourDbContext,如果还有工厂类,也要把它加进链里。
第二步:手动实例化真实依赖(简单测试首选)
如果只是做单次测试,不想引入复杂的DI容器,直接手动一层层实例化就行:
创建真实的DbContext实例
用你项目里的连接字符串(或者专门的测试库连接字符串)初始化DbContext:// 可以从测试项目的App.config里读取连接字符串,避免硬编码 var dbContext = new YourDbContext("Server=.;Database=YourTestDb;Trusted_Connection=True;");实例化仓储的真实实现
把DbContext传给仓储:var workPlaceRepo = new WorkPlaceRepository(dbContext);实例化服务的真实实现
把仓储(如果有工厂的话也加上)传给服务:// 如果服务还依赖工厂 var workPlaceFactory = new WorkPlaceFactory(); var workPlaceService = new WorkPlaceService(workPlaceRepo, workPlaceFactory); // 没有工厂的话就直接传仓储 // var workPlaceService = new WorkPlaceService(workPlaceRepo);实例化控制器并调用方法
把服务传给控制器,现在就能调用Index()拿到真实结果了:var controller = new WorkPlacesController(workPlaceService); var result = controller.Index() as ViewResult; var workPlaces = result.Model as List<WorkPlace>; // 接下来就可以断言结果是否符合预期了
第三步:用DI容器简化注入(复杂场景推荐)
如果你的依赖关系比较多,手动实例化太繁琐,可以用DI容器(比如Autofac、Ninject、Unity)来管理,一次配置就能重复用。
以Autofac为例:
先在测试项目里装Autofac的NuGet包:
Install-Package Autofac配置容器,注册所有真实依赖
var builder = new ContainerBuilder(); // 注册DbContext,用真实连接字符串(对应测试项目App.config中的配置) builder.Register(c => new YourDbContext("YourDbContext")) .As<YourDbContext>() .InstancePerLifetimeScope(); // 注册仓储接口和真实实现 builder.RegisterType<WorkPlaceRepository>() .As<IWorkPlaceRepository>(); // 注册服务接口和真实实现 builder.RegisterType<WorkPlaceService>() .As<IWorkPlaceService>(); // 注册控制器 builder.RegisterType<WorkPlacesController>(); var container = builder.Build();从容器里解析控制器
容器会自动帮你把所有依赖都注入好:var controller = container.Resolve<WorkPlacesController>(); var result = controller.Index();
几个关键注意事项
- 用专门的测试数据库:千万别直接连生产库!建个测试库,测试前可以初始化测试数据,测试后清空,避免污染真实数据。
- 管理连接字符串:把测试用的连接字符串放在测试项目的
App.config里,别硬编码,方便修改:<connectionStrings> <add name="YourDbContext" connectionString="Server=.;Database=YourTestDb;Trusted_Connection=True;" providerName="System.Data.SqlClient" /> </connectionStrings> - 控制器上下文(如果需要):如果你的
Index()用到了Session、Request这些东西,得手动给控制器设置上下文:
要是只是测试数据查询逻辑,这一步可以跳过。controller.ControllerContext = new ControllerContext { Controller = controller, RequestContext = new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()) };
内容的提问来源于stack exchange,提问作者Paulo Jardim
相关产品推荐
相关产品推荐

