Integration testing with in-memory IdentityServer
<p>I have an API that uses IdentityServer4 for token validation.
I want to unit test this API with an in-memory TestServer. I'd like to host the IdentityServer in the in-memory TestServer.</p>
<p>I have managed to create a token from the IdentityServer.</p>
<p>This is how far I've come, but I get an error &quot;Unable to obtain configuration from http://localhost:54100/.well-known/openid-configuration&quot;</p>
<p>The Api uses [Authorize]-attribute with different policies. This is what I want to test.</p>
<p>Can this be done, and what am I doing wrong?
I have tried to look at the source code for IdentityServer4, but have not come across a similar integration test scenario.</p>

<pre class="lang-cs prettyprint-override"><code>protected IntegrationTestBase()
{
    var startupAssembly = typeof(Startup).GetTypeInfo().Assembly;

    _contentRoot = SolutionPathUtility.GetProjectPath(@&quot;&lt;my project path&gt;&quot;, startupAssembly);
    Configure(_contentRoot);
    var orderApiServerBuilder = new WebHostBuilder()
        .UseContentRoot(_contentRoot)
        .ConfigureServices(InitializeServices)
        .UseStartup&lt;Startup&gt;();
    orderApiServerBuilder.Configure(ConfigureApp);
    OrderApiTestServer = new TestServer(orderApiServerBuilder);

    HttpClient = OrderApiTestServer.CreateClient();
}

private void InitializeServices(IServiceCollection services)
{
    var cert = new X509Certificate2(Path.Combine(_contentRoot, &quot;idsvr3test.pfx&quot;), &quot;idsrv3test&quot;);
    services.AddIdentityServer(options =&gt;
        {
            options.IssuerUri = &quot;http://localhost:54100&quot;;
        })
        .AddInMemoryClients(Clients.Get())
        .AddInMemoryScopes(Scopes.Get())
        .AddInMemoryUsers(Users.Get())
        .SetSigningCredential(cert);
        
    services.AddAuthorization(options =&gt;
    {
        options.AddPolicy(OrderApiConstants.StoreIdPolicyName, policy =&gt; policy.Requirements.Add(new StoreIdRequirement(&quot;storeId&quot;)));
    });
    services.AddSingleton&lt;IPersistedGrantStore, InMemoryPersistedGrantStore&gt;();
    services.AddSingleton(_orderManagerMock.Object);
    services.AddMvc();
}

private void ConfigureApp(IApplicationBuilder app)
{
    app.UseIdentityServer();
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    var options = new IdentityServerAuthenticationOptions
    {
        Authority = _appsettings.IdentityServerAddress,
        RequireHttpsMetadata = false,

        ScopeName = _appsettings.IdentityServerScopeName,
        AutomaticAuthenticate = false
    };
    app.UseIdentityServerAuthentication(options);
    app.UseMvc();
}
</code></pre>
<p>And in my unit-test:</p>
<pre class="lang-cs prettyprint-override"><code>private HttpMessageHandler _handler;
const string TokenEndpoint = &quot;http://localhost/connect/token&quot;;
public Test()
{
    _handler = OrderApiTestServer.CreateHandler();
}

[Fact]
public async Task LeTest()
{
    var accessToken = await GetToken();
    HttpClient.SetBearerToken(accessToken);

    var httpResponseMessage = await HttpClient.GetAsync(&quot;stores/11/orders/asdf&quot;); // Fails on this line

}

private async Task&lt;string&gt; GetToken()
{
    var client = new TokenClient(TokenEndpoint, &quot;client&quot;, &quot;secret&quot;, innerHttpMessageHandler: _handler);

    var response = await client.RequestClientCredentialsAsync(&quot;TheMOON.OrderApi&quot;);

    return response.AccessToken;
}
</code></pre>