Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

integration testing ASP.NET 5 Identity

Im trying to get integration testing working for my ASP.NET 5 MVC6 Api using EF7. Im using the default project that comes with Identity already implemented.

Here is the action im trying to test in my controller (gets all the children for the logged in user)

[Authorize]    
[HttpGet("api/children")]
public JsonResult GetAllChildren()
{
    var children = _repository.GetAllChildren(User.GetUserId());
    var childrenViewModel = Mapper.Map<List<ChildViewModel>>(children);
    return Json(childrenViewModel);
}

In my test project I create an inmemory database and then do the integration tests against that

Here is the Base I use for the integration tests

public class IntegrationTestBase 
{
    public TestServer TestServer;
    public IntegrationTestBase()
    {
        TestServer = new TestServer(TestServer.CreateBuilder().UseStartup<TestStartup>());
    } 
}

And here is the TestStartup (where i override the method that adds SQLServer with one that adds the inmemory test database)

public class TestStartup : Startup
{
    public TestStartup(IHostingEnvironment env) : base(env)
    {
    }

    public override void AddSqlServer(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddInMemoryDatabase()
            .AddDbContext<ApplicationDbContext>(options => {
                options.UseInMemoryDatabase();
            });
    }

}

And the test for the action

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
    }
}

Can anybody point me in the right direction on how to potentially set the CurrentPrincipal or some other way to get my integration tests working?

like image 259
Stemo Avatar asked Dec 29 '15 19:12

Stemo


People also ask

What is WebApplicationFactory?

WebApplicationFactory<TEntryPoint> is used to create a TestServer for the integration tests. TEntryPoint is the entry point class of the SUT, usually Program.

What is the difference between integration and E2E tests?

As a rule, integration testing targets two modules that need to interact to fulfill some function stipulated by the requirements. In practice, this effort boils down to checking if the query delivers the expected result. Unlike integration testing, E2E testing immediately checks how the entire system works.


1 Answers

The question is how you are authenticating in your test? On your project startup you may add a virtual function like below

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
    });
}

And then derived a startup class in your test project and override the authentication method to do nothing or to add claim you can use a middle-ware as below

TestStartUp

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

Middle ware class

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")
        };
    }
}
like image 109
MJK Avatar answered Nov 11 '22 11:11

MJK