c# - 与 asp.net 核心的集成测试(没有视图的控制器测试)
问题描述
我正在尝试设置一个测试项目来测试具有身份和数据库的控制器,而无需定义视图。
我有一个单元测试项目,我可以通过实例化它来测试我的控制器,将 dbContext 传递给构造函数。
public class EventControllerTests
{
private readonly IEventRepository _eventRepository;
private readonly EventController _controller;
private readonly AppDbContext dbContext;
const string cn = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=EventDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
public EventControllerTests()
{
var options = new DbContextOptionsBuilder<EVNTS.Web.Database.AppDbContext>()
.UseSqlServer(cn).Options;
dbContext = new EVNTS.Web.Database.AppDbContext(options);
// Arrange
_eventRepository = new EventRepository(dbContext);
_controller = new EVNTS.Web.Controllers.EventController(_eventRepository);
}
[Fact]
public void ActionIndexTest()
{
// Act
var result = _controller.Index(1);
// Assert
var model = (Event)result.Model;
Assert.Equal(1, model.Id);
}
}
我有一个使用 WebApplicationFactory 的集成测试项目
public class BasicTests : IClassFixture<WebApplicationFactory<EVNTS.Startup>>
{
private readonly WebApplicationFactory<EVNTS.Startup> _factory;
private readonly HttpClient _client;
public BasicTests(WebApplicationFactory<EVNTS.Startup> factory)
{
_factory = factory;
_client = _factory.CreateClient();
}
[Theory]
[InlineData("/")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
{
// Act
var response = await _client.GetAsync(url);
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
[Fact]
public async Task TestUserRegistration()
{
var s = _factory.Services.GetRequiredService<EVNTS.Web.Repositories.IEventRepository>();
var url = "/user/register";
var inputModel = new EVNTS.Web.ViewModels.RegisterModel()
{
UserName = "eric",
Password = "123456",
ConfirmPassword = "123456"
};
var sObj = JsonSerializer.Serialize(inputModel);
var content = new StringContent(sObj, Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _client.PostAsync(url, content);
var result = response.Content.ReadAsStringAsync();
}
}
问题是,使用第二个选项,必须创建视图,我需要使用 AngleSharp 之类的库来测试结果。
我想要介于两者之间的东西,我可以直接调用构造函数并测试结果视图,但 DI 会为我注入 UserManager 和 dbContext。
有任何想法吗?
干杯
这是控制器:
public class UserController : Controller
{
private readonly UserManager<User> _userManager;
public UserController(UserManager<User> userManager)
{
_userManager = userManager;
}
[HttpPost]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
IdentityResult? result=null;
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.UserName);
if (user == null)
{
user = new User
{
Id = Guid.NewGuid(),
UserName = model.UserName,
};
result = await _userManager.CreateAsync(user, model.Password);
}
}
return View(result);
}
}
解决方案
当您想在集成测试条件下检查控制器的结果而不检查视图时,我也发现这有时很有用。
您可以使用依赖注入并从WebApplicationFactory
.
using (var serviceScope = Factory.Services.CreateScope())
{
var sut= serviceScope.ServiceProvider.GetService<YourController>();
}
要完成这项工作,您必须调用方法AddControllersAsServices()
在Startup.cs
DI 容器中注册控制器
services.AddControllersWithViews(options => { options.ConfigureMvcOptionsForPortalModule(); })
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddControllersAsServices();//add controller in DI to access it in integration testing
推荐阅读
- python - Python 速成班 - 外星人入侵 - 错误背景
- pandas - 按列合并 Pandas DataFrame
- python - 如何在 Lark parser python 中解析条件语句?
- applescript - 如果存在对话框,请使用 Applescript 单击某个按钮
- unity3d - Unity 触发对其他脚本的引用
- javascript - 保持固定标题的水平滚动位置与正文同步
- ruby-on-rails - Rails 6 + Webpacker 添加和使用 yaml-loader
- python - Django 视图显示相同的内容。django 视图在哪里控制?
- jolt - 使用 JOLT 将 json 数组中的值转换为另一个值
- vue.js - 为什么子组件的 v-model 不会从发射更改为父组件?