Identityserver4: Using Microsoft.AspNetCore.TestHost.TestServer

Created on 1 Feb 2017  路  2Comments  路  Source: IdentityServer/IdentityServer4

Do you have any examples or pointers on how to get IdentityServer4 and TestServer to work well together? Here's my attempt.

I have an ASP.Net Core project that hosts both MVC and IdentityServer4.
I also have an xunit integration test that uses Microsoft.AspNetCore.TestHost.TestServer to call an MVC action. In the constructor of this test, I'm setting up the HttpClient, and I need to perform the handshake with IdentityServer4 to get a bearer token. However, I'm not having much luck.

Since TestServer creates its own instance of HttpClient, I had to create a new version of IdentityServer4's TestDiscoveryClient which accepts an HttpClient. And this is my resulting code:

`

public class ControllerTests
{
    private TestServer _server;
    private HttpClient _client;

    public ControllerTests()
    {
        // Arrange
        var contentRoot = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\..\..\src\MyApi");
        _server = new TestServer(new WebHostBuilder()
            .UseContentRoot(contentRoot)
            //.UseWebRoot(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"))
            .UseStartup<Startup>()
            );

        _client = _server.CreateClient();

        // discover endpoints from metadata
        var disco = TestDiscoveryClient.GetAsync(_client).Result;
        if (disco.IsError)
        {
            throw new Exception(disco.Error);
        }

        // request token
        var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
        var tokenResponse = tokenClient.RequestClientCredentialsAsync("api1").Result;

        if (tokenResponse.IsError)
        {
// ********* THROWS EXCEPTION HERE.  Error is "Not Found".
            throw new Exception(tokenResponse.Error);
        }

        _client.SetBearerToken(tokenResponse.AccessToken);
    }

    [Fact]
    public async Task Controller_Test1() // Naming convention  <Feature>_<Action>_<State>_<FailureOrSuccess>
    {
        var response = await _client.PostAsJsonAsync("/api/Test");
        response.EnsureSuccessStatusCode();

        var responseString = await response.Content.ReadAsStringAsync();

        // Assert
        Assert.Equal("true", responseString);
    }

}

`

This code gets throws an exception because I get a "Not Found" response back from IdentityServer4. I've marked in the code where the exception occurs.

question

Most helpful comment

Actually, writing this out helped me figure it out. The key was to use _server.CreateHandler() to create an HttpMessageHandler to pass to both the DiscovertClient constructor and the TokenClient constructor. That means you can't use the DiscoveryClient.GetAsync static method, though.

All 2 comments

Actually, writing this out helped me figure it out. The key was to use _server.CreateHandler() to create an HttpMessageHandler to pass to both the DiscovertClient constructor and the TokenClient constructor. That means you can't use the DiscoveryClient.GetAsync static method, though.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ekarlso picture ekarlso  路  3Comments

brockallen picture brockallen  路  3Comments

Aravind1729 picture Aravind1729  路  3Comments

user1336 picture user1336  路  3Comments

createroftheearth picture createroftheearth  路  3Comments