.NET 6 ASP Web API中xUnit+Moq调用服务类时DbContext为空的解决方法
.NET 6 Web API单元测试:解决UserService中DbContext为空的问题
问题场景
在.NET 6的ASP.NET Web API中使用xUnit+Moq进行单元测试时,遇到以下问题:
- UserService通过依赖注入引入DbContext,但调用其
GetUsers方法时DbContext为空 - 相关组件:
UserController控制器、UserService服务类、IUserService接口 - 原测试代码示例:
var result = new BaseResponseModel() { StatusCode = (int)ResponseType.Success, Data = new UserModel { Id = 10002 }, Message = null }; var userrepo = new Mock<UserService>(); userrepo.Setup(x => x.GetUsers(It.IsAny<long>())).ReturnsAsync(result); var controller = new UserController(userrepo.Object); BaseResponseModel response = await controller.GetEmployerUserList(10002);
问题原因
- 错误Mock了
UserService具体实现类而非抽象接口IUserService,Moq无法处理类的依赖注入逻辑,导致DbContext未初始化 - 若测试
UserService本身,未提供有效的DbContext实例,引发数据库访问时的空引用异常
解决方案
方案1:测试控制器(隔离数据库依赖)
控制器依赖的是IUserService接口,单元测试时直接Mock该接口,完全隔离数据库层,无需初始化DbContext:
// 1. Mock抽象接口IUserService而非具体类 var userServiceMock = new Mock<IUserService>(); // 2. 配置接口方法的返回值 var mockResult = new BaseResponseModel() { StatusCode = (int)ResponseType.Success, Data = new UserModel { Id = 10002 }, Message = null }; userServiceMock.Setup(x => x.GetUsers(It.IsAny<long>())).ReturnsAsync(mockResult); // 3. 注入Mock对象到控制器 var controller = new UserController(userServiceMock.Object); // 4. 执行测试并验证结果 BaseResponseModel response = await controller.GetEmployerUserList(10002); Assert.Equal((int)ResponseType.Success, response.StatusCode); Assert.Equal(10002, ((UserModel)response.Data).Id);
方案2:测试UserService(初始化测试用DbContext)
若要测试UserService的数据库访问逻辑,可使用EF Core内存数据库模拟真实数据库:
- 安装EF Core内存数据库包:
Install-Package Microsoft.EntityFrameworkCore.InMemory
- 编写测试代码:
// 1. 配置内存DbContext var options = new DbContextOptionsBuilder<YourDbContext>() .UseInMemoryDatabase(databaseName: "TestUserDb") .Options; // 2. 初始化测试用DbContext并添加测试数据 using var context = new YourDbContext(options); context.Users.Add(new User { Id = 10002, Name = "Test User" }); context.SaveChanges(); // 3. 实例化UserService,传入测试用DbContext var userService = new UserService(context); // 4. 调用方法并验证结果 var response = await userService.GetUsers(10002); Assert.Equal((int)ResponseType.Success, response.StatusCode); Assert.Equal(10002, ((UserModel)response.Data).Id);
内容的提问来源于stack exchange,提问作者Barkha Bhavsar
相关产品推荐
相关产品推荐

