
IdentityModel is an open-source library developed by Dominick Baier and Brock Allen which does an excellent job of simplifying interactions with OAuth 2.0 and OpenID Connect servers.
However, when it comes to unit testing, it can appear on the surface to be somewhat difficult to create certain objects that need to be instantiated on demand for mocking purposes.
The IdentityModel library provides a set of HttpClient
extension methods for calling token endpoints, most of which return an instance of the TokenResponse
class. At first glance, there doesn’t seem to be a way to set TokenResponse
property values, but it isn’t too difficult to work around this once you know how.
In this article, I will demonstrate how to create an instance of the TokenResponse
class and populate its properties with mock data that you can use in your unit tests.
Prerequisites
Before getting started, let’s cover a few prerequisites and assumptions that are being made to manage expectations.
First of all, this article assumes that you are already somewhat familiar with the IdentityModel library or that you are currently learning about it and can find out what you need to know about its general usage via the IdentityModel Documentation.
Second, it is assumed that you are already familiar with unit testing and mocking frameworks and can therefore understand the concepts behind why one would need to generate data on demand that is usually returned by a call to an API, as opposed to calling an external service directly in a unit test.
Lastly, you’ll need to have the relevant NuGet packages installed. I recommend the latest version of the IdentityModel NuGet package. Regarding unit testing, my personal preference currently is to use xUnit alongside the Moq mocking framework. However, aside from IdentityModel, your choice of libraries and frameworks does not matter as the focus of this article is on the TokenResponse
class, not on how to write unit tests.
Problem analysis
The problem that you’ll inevitably run into when writing unit tests that involve the IdentityModel HttpClient
extension methods is the apparent restrictiveness of the TokenResponse
class, since most of the extension methods return this type.
The TokenResponse
class poses a problem for unit testing since all of its public properties lack setters and there doesn’t appear to be a way to pass values via a constructor or influence the shape of the object after it has been created.
This means that when we create a new TokenResponse
object instance and try to set one or more of its properties, we’ll get a compile-time error like the one shown below.

TokenResponse
properties directlyThe above restriction causes issues when writing a unit test that needs to call a method that returns a TokenResponse
object, as it appears that the object can’t be transformed into a shape needed to simulate different responses from token endpoints.
Let’s dig into why the TokenResponse
properties can’t be set directly. The source code of the TokenResponse
class from Version 6.0.0 of the IdentityModel library has been reproduced below for reference.
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. namespace IdentityModel.Client; /// <summary> /// Models a response from an OpenID Connect/OAuth 2 token endpoint /// </summary> /// <seealso cref="IdentityModel.Client.ProtocolResponse" /> public class TokenResponse : ProtocolResponse {     /// <summary>     /// Gets the access token.     /// </summary>     /// <value>     /// The access token.     /// </value>     public string AccessToken => TryGet(OidcConstants.TokenResponse.AccessToken);     /// <summary>     /// Gets the identity token.     /// </summary>     /// <value>     /// The identity token.     /// </value>     public string IdentityToken => TryGet(OidcConstants.TokenResponse.IdentityToken);     /// <summary>     /// Gets the scope.     /// </summary>     /// <value>     /// The scope.     /// </value>     public string Scope => TryGet(OidcConstants.TokenResponse.Scope);             /// <summary>     /// Gets the issued token type.     /// </summary>     /// <value>     /// The issued token type.     /// </value>     public string IssuedTokenType => TryGet(OidcConstants.TokenResponse.IssuedTokenType);             /// <summary>     /// Gets the type of the token.     /// </summary>     /// <value>     /// The type of the token.     /// </value>     public string TokenType => TryGet(OidcConstants.TokenResponse.TokenType);     /// <summary>     /// Gets the refresh token.     /// </summary>     /// <value>     /// The refresh token.     /// </value>     public string RefreshToken => TryGet(OidcConstants.TokenResponse.RefreshToken);     /// <summary>     /// Gets the error description.     /// </summary>     /// <value>     /// The error description.     /// </value>     public string ErrorDescription => TryGet(OidcConstants.TokenResponse.ErrorDescription);     /// <summary>     /// Gets the expires in.     /// </summary>     /// <value>     /// The expires in.     /// </value>     public int ExpiresIn     {         get         {             var value = TryGet(OidcConstants.TokenResponse.ExpiresIn);             if (value != null)             {                 if (int.TryParse(value, out var theValue))                 {                     return theValue;                 }             }             return 0;         }     } }
Notice how the TokenResponse
class inherits from the ProtocolResponse
 class.
All of the properties within the TokenResponse
class call the TryGet
method defined on the ProtocolResponse
base class, which attempts to retrieve the value of the specified field from the underlying JSON content.
The ProtocolResponse
class also forms part of the secret for creating TokenResponse
class instances with mock data which we’ll find out about shortly.
Untestable code?
Suppose our application is a ‘machine-to-machine’ program and only needs to obtain tokens based on the Client Credentials OAuth 2.0 flow. In this case, we can define a simple interface for our own token client that can retrieve a token based on the specified client credentials, as follows.
using IdentityModel.Client; /// <summary> /// Token Client interface. /// </summary> public interface ITokenClient {     #region Methods    Task<TokenResponse> GetTokenResponseAsync(ClientCredentialsTokenRequest request);     #endregion }
We can then create a class that implements the ITokenClient
interface and has the responsibility of getting tokens from the server. The GetTokenResponseAsync
method does this by delegating to the appropriate IdentityModel HttpClient
extension method, i.e. RequestClientCredentialsTokenAsync
.
using IdentityModel.Client; /// <summary> /// Implements the retrieval logic for tokens. /// </summary> public class TokenClient : ITokenClient {     #region Readonlys     private readonly HttpClient _httpClient;     #endregion     #region Constructor     /// <summary>     /// Constructor.     /// </summary>     /// <param name="httpClient">The HTTP Client</param>     public TokenClient(HttpClient httpClient)     {         _httpClient = httpClient;     }     #endregion     #region Methods     /// <summary>     /// Gets a Token Response from the server.     /// </summary>     /// <param name="request">The Client Credentials Token Request</param>     /// <returns><see cref="TokenResponse"/></returns>     public async Task<TokenResponse> GetTokenResponseAsync(ClientCredentialsTokenRequest request)     {         return await _httpClient.RequestClientCredentialsTokenAsync(request);     }     #endregion }
To write a unit test that can call GetTokenResponseAsync
we’ll need to find a way to mock this method. Otherwise, the test would be making a real API call to a token endpoint and it wouldn’t be a unit test anymore!
But how can we set up a mock when it isn’t possible to populate the properties of a TokenResponse
object directly?
That’s where the ProtocolResponse
class comes in.
ProtocolResponse to the rescue
The ProtocolResponse
class contains a couple of static factory methods; one of which is named FromHttpResponseAsync
. This method takes a HttpResponseMessage
object as an input parameter and generates a response from this. You can see the method in action below.
using IdentityModel.Client; using System.Net; var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK); var tokenResponse       = await ProtocolResponse.FromHttpResponseAsync<TokenResponse>(httpResponseMessage);
In the above code, a HttpResponseMessage
object is first created with an OK
status code. The FromHttpResponseAsync
method is then called, passing in the HttpResponseMessage
instance and specifying the response type to return as TokenResponse
.
This doesn’t quite do the job though, remember the TryGet
method calls within the TokenResponse
class? The above code isn’t going to generate the JSON content needed for the TryGet
method to succeed in returning values for the TokenResponse
properties such as AccessToken
and Scope
.
Content creation
As it turns out, we can update the code such that it creates the required JSON content quite easily. We do this by setting the Content
property of the HttpResponseMessage
object with the result of a call to the static JsonContent.Create
method, as shown in the updated code sample below.
using IdentityModel.Client; using System.Net; using System.Net.Http.Json; var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK) {     Content = JsonContent.Create(new     {         access_token = "token",         expires_in   = 3600     }) }; var tokenResponse = await ProtocolResponse.FromHttpResponseAsync<TokenResponse>(httpResponseMessage);
The above code passes an anonymous object containing properties that are named according to the constants that are defined within the IdentityModel OidcConstants.TokenResponse
class.
After creating a TokenResponse
object using the above code, the AccessToken
and ExpiresIn
properties will return the values that have been specified within the JSON content of the HttpResponseMessage
object.
Going further
We can take things a step further by creating a class that will hold the content we want to serialise and store as the JSON content for the response. The class below shows the implementation of this for reference.
using IdentityModel; using System.Text.Json.Serialization; /// <summary> /// Models the content of a response from an OpenID Connect / OAuth 2 token endpoint. /// </summary> public class TokenResponseContent {     #region Properties     /// <summary>     /// The access token.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.AccessToken)]     public string? AccessToken { get; set; }     /// <summary>     /// The identity token.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.IdentityToken)]     public string? IdentityToken { get; set; }     /// <summary>     /// The scope.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.Scope)]     public string? Scope { get; set; }     /// <summary>     /// The issued token type.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.IssuedTokenType)]     public string? IssuedTokenType { get; set; }     /// <summary>     /// The type of the token.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.TokenType)]     public string? TokenType { get; set; }     /// <summary>     /// The refresh token.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.RefreshToken)]     public string? RefreshToken { get; set; }     /// <summary>     /// The error description.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.ErrorDescription)]     public string? ErrorDescription { get; set; }     /// <summary>     /// The expires in.     /// </summary>     [JsonPropertyName(OidcConstants.TokenResponse.ExpiresIn)]     public int ExpiresIn { get; set; }     #endregion }
The above class is very similar to the original TokenResponse
class, as it has all of the same properties. However, the properties now have public setters and have been decorated with a JsonPropertyName
attribute so that when the class is serialised the property names will match what the TryGet
method that was mentioned previously is expecting.
With the TokenResponseContent
class defined, we can now create a simplified helper method where the details of how TokenResponse
objects are created is hidden from view.
/// <summary> /// Creates a <see cref="TokenResponse"/> object on demand. /// </summary> /// <param name="statusCode">The HTTP status code of the response</param> /// <param name="tokenResponseContent">The response content</param> /// <returns><see cref="TokenResponse"/></returns> public static async Task<TokenResponse> CreateTokenResponseAsync(   HttpStatusCode statusCode,   TokenResponseContent tokenResponseContent) {     var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)     {         Content = JsonContent.Create(tokenResponseContent)     };    return await ProtocolResponse.FromHttpResponseAsync<TokenResponse>(httpResponseMessage); }
This helper method can now be called from unit tests to create TokenResponse
objects on demand.
Since the TokenResponseContent
class wraps the main properties that we need to serialise as content, the above implementation only requires two parameters to be specified, which will help to simply unit test setup code.
We can use the helper method in place of the code that was shown previously, as per the code sample below.
using IdentityModel.Client; using System.Net; using System.Net.Http.Json; var tokenResponseContent = new TokenResponseContent {     AccessToken = "token",     ExpiresIn   = 3600,
Scope = "api" }; TokenResponse tokenResponse = await CreateTokenResponseAsync(HttpStatusCode.OK, tokenResponseContent);
The TokenResponseContent
class allows us to simulate a variety of different responses by setting the relevant property values. For example, we could set the Error
property which would cause the IsError
property on the TokenResponse
object to return true, simulating an unauthorised token request.
Mocking
If you are using a mocking framework such as Moq you can set up mocks that return TokenResponse
objects using the helper method defined in the previous section.
The code sample below demonstrates a quick example of this in action (using statements omitted).
var tokenResponse = await CreateTokenResponseAsync(HttpStatusCode.OK, new TokenResponseContent {     AccessToken = "token",     ExpiresIn   = 3600 }); var tokenRequest = new ClientCredentialsTokenRequest {     Address      = "https://demo.duendesoftware.com/connect/token",     ClientId     = "id",     ClientSecret = "secret" }; var tokenClientMock = new Mock<ITokenClient>(); tokenClientMock.Setup(c => c.GetTokenResponseAsync(tokenRequest)).ReturnsAsync(tokenResponse);
When using Moq, you can get a mock ITokenClient
instance by accessing the Value
property of the Mock
object. This object instance can then be passed to any objects that need it so that unit tests can be implemented.
With all of the above in place, any tests that call the GetTokenResponseAsync
method (either directly or indirectly) can now run reliably and you can set up different mocks to simulate both successful and unsuccessful responses from the token server.
Summary
In this article, I have shown how you can create an instance of the IdentityModel TokenResponse
class and populate its internal content for the purposes of mocking when writing unit tests.
I first looked at the specifics of the problem and demonstrated why at a first glance the TokenResponse
class doesn’t appear to make it easy to set things up for unit testing.
I then walked through how you can resolve the problem by using the ProcotolResponse.FromHttpResponseAsync
method and at the same time generate the JSON content that is needed to simulate the responses that can be returned by a token server.
I finished by providing a quick example of how to mock the return value of the custom GetTokenResponseAsync
method.
Assuming you already know how to write effective unit tests, I trust that you will have found this article helpful for getting you past the initial hurdle of how to create TokenResponse
object instances with suitable property values. For those of you who aren’t currently familiar with writing unit tests, that will be a topic for another day!
Comments
Morten
I was struggling with this exact thing, so this article was incredibly helpful. Thank you!
April 12, 2023Jonathan Crozier
Hi Morten, thanks for the comment. I’m very pleased you found the article helpful 😀
April 12, 2023