集成测试ASP.NET 5 Identity

Ste*_*emo 6 asp.net integration-testing asp.net-identity asp.net-core

我试图使用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);
}
Run Code Online (Sandbox Code Playgroud)

在我的测试项目中,我创建了一个内存数据库,然后对其进行集成测试

这是我用于集成测试的Base

public class IntegrationTestBase 
{
    public TestServer TestServer;
    public IntegrationTestBase()
    {
        TestServer = new TestServer(TestServer.CreateBuilder().UseStartup<TestStartup>());
    } 
}
Run Code Online (Sandbox Code Playgroud)

这里是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();
            });
    }

}
Run Code Online (Sandbox Code Playgroud)

并且测试了行动

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
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以指出我正确的方向如何设置CurrentPrincipal或其他方式让我的集成测试工作?

MJK*_*MJK 1

问题是你如何在测试中进行身份验证?在项目启动时,您可以添加如下所示的虚拟函数

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
    });
}
Run Code Online (Sandbox Code Playgroud)

然后在您的测试项目中派生一个启动类并覆盖身份验证方法以不执行任何操作或添加声明您可以使用中间件,如下所示

测试启动

internal TestStartUp : Startup
{
    protected override void UseAuthentication(IApplicationBuilder app)
    {
        app.UseMiddleware<TestAuthMiddlewareToByPass>();
    }
}
Run Code Online (Sandbox Code Playgroud)

中件类

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")
        };
    }
}
Run Code Online (Sandbox Code Playgroud)