我正在尝试使用EF7为我的ASP.NET 5 MVC6 Api进行集成测试。我使用的是已经实现的Identity附带的默认项目。
以下是我试图在控制器中测试的操作(获取登录用户的所有子项)
[Authorize]
[HttpGet("api/children")]
public JsonResult GetAllChildren()
{
var children = _repository.GetAllChildren(User.GetUserId());
var childrenViewModel = Mapper.Map<List<ChildViewModel>>(children);
return Json(childrenViewModel);
}
在我的测试项目中,我创建了一个内存数据库,然后对进行集成测试
这是我用于集成测试的基础
public class IntegrationTestBase
{
public TestServer TestServer;
public IntegrationTestBase()
{
TestServer = new TestServer(TestServer.CreateBuilder().UseStartup<TestStartup>());
}
}
这里是TestStartup(我用添加内存测试数据库的方法覆盖添加SQLServer的方法)
public class TestStartup : Startup
{
public TestStartup(IHostingEnvironment env) : base(env)
{
}
public override void AddSqlServer(IServiceCollection services)
{
services.AddEntityFramework()
.AddInMemoryDatabase()
.AddDbContext<ApplicationDbContext>(options => {
options.UseInMemoryDatabase();
});
}
}
以及动作的测试
public class ChildTests : IntegrationTestBase
{
[Fact]
public async Task GetAllChildren_Test()
{
//TODO Set Current Principal??
var result = await TestServer.CreateClient().GetAsync("/api/children");
result.IsSuccessStatusCode.Should().BeTrue();
var body = await result.Content.ReadAsStringAsync();
body.Should().NotBeNull();
//TODO more asserts
}
}
有人能为我指明正确的方向,告诉我如何潜在地设置CurrentPrincipal或其他方式来让我的集成测试工作吗?
问题是如何在测试中进行身份验证?在你的项目启动时,你可以添加一个虚拟功能,如下面的
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// ...
UseAuthentication(app);
// ...
app.UseMvcWithDefaultRoute();
}
protected virtual void UseAuthentication(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
}
然后在您的测试项目中派生出一个启动类,并覆盖身份验证方法以不做任何事情或添加声明您可以使用下面的中间件
测试启动
internal TestStartUp : Startup
{
protected override void UseAuthentication(IApplicationBuilder app)
{
app.UseMiddleware<TestAuthMiddlewareToByPass>();
}
}
中间件类
public class TestAuthMiddlewareToByPass
{
public const string TestingCookieAuthentication = "TestCookieAuthentication";
private readonly RequestDelegate _next;
public TestAuthMiddlewareToByPass(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// fake user
ClaimsIdentity claimsIdentity = new ClaimsIdentity(Claims(), TestingCookieAuthentication);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
context.User = claimsPrincipal;
await _next(context);
}
protected virtual List<Claim> Claims()
{
return new List<Claim>
{
new Claim(ClaimTypes.Name, "admin"),
new Claim(ClaimTypes.Role, "admin")
};
}
}