我正在尝试为asp.net核心Web API设置一个测试项目。我需要处理几个专业:
UserManger
来播种一些用户根据Documentation,我应该导出WebApplicationFactory
的形式并覆盖ConfigureWebHost
方法。所以我做到了:
public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
public BeepDbContext Context;
public UserManager<User> UserMgr;
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
ServiceDescriptor descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<BeepDbContext>));
if (descriptor != null) services.Remove(descriptor);
services.AddDbContext<BeepDbContext>(o =>
o.UseSqlServer("Server=.\\SQLEXPRESS;Database=BeepTest;Trusted_Connection=true;"));
ServiceProvider provider = services.BuildServiceProvider();
using (IServiceScope scope = provider.CreateScope())
{
Context = scope.ServiceProvider.GetRequiredService<BeepDbContext>();
Context.Database.Migrate();
UserMgr = scope.ServiceProvider.GetRequiredService<UserManager<User>>(); // <--- fails here
}
});
}
}
这是我的测试班:
public class UserControllerTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly ITestOutputHelper _output;
private readonly CustomWebApplicationFactory _factory;
public UserControllerTests(ITestOutputHelper output, CustomWebApplicationFactory factory)
{
_output = output;
_factory = factory;
}
[Fact]
public async Task Login()
{
HttpClient client = _factory.CreateClient();
HttpResponseMessage result = await client.PostAsJsonAsync("/api/auth/login", new UserForLoginDto()
{
Username = "user",
Password = "P@ssw0rd"
});
_output.WriteLine(result.StatusCode.ToString());
_output.WriteLine(result.Content.ReadAsStringAsync().Result);
Assert.Equal(HttpStatusCode.OK, result.StatusCode);
}
}
这在我尝试获得UserManager
的行上失败,该行说没有为该类型注册的服务。我也无法使它使用测试项目中的配置文件而不是主项目。因此,我对连接字符串进行了硬编码。经过一些调试后,我发现ConfigureServices
类中的startup
方法是在我重写的方法之后执行的。所以我认为这解释了为什么我无法获得用户管理器。我不明白的是,我做错了什么或如何正确完成?
据我所知,我所做的工作与文档或文档中提供的sample app差不多。