How to set global variable to use across multiple classes in test project

42 Views Asked by At

I am using XUnit with WebApplicationFactory to write integration tests for my C# API Application

GetTokenControllerTest will call GetToken() to store the Auth code in AccessToken which can then be used through out the class. Setting the header value with the AUthorization, allowing me to access authoirsed end points in the controller

    public class TokenDTO
{
  public string AccessToken { get; set; }
}

public class GetTokenControllerTest : IClassFixture<TokenDTO> 
{
    private readonly HttpClient _client;
    private readonly TokenDTO _tokenDTO;

    public GetTokenControllerTest(TokenDTO tokenDTO)
    {
         _tokenDTO = tokenDTO;
         var factory = new WebApplicationFactory<Program>();
            _client = factory.CreateClient();
    }

       [Fact, TestPriority(1)]
        public async Task GetToken()
        {
                TokenRequestDto dto = new TokenRequestDto();
        dto.Email = "[email protected]";
        dto.Password = "123456";

                var payload = JsonConvert.SerializeObject(dto);
                var content = new StringContent(payload, Encoding.UTF8, "application/json");
                var GetTokenContentsResponse = await _client.PostAsync("/api/Tokens/Auth", content);

                var TokenJson = GetTokenContentsResponse.Content.ReadAsStringAsync().Result;

                var TokenDTO = JsonConvert.DeserializeObject<TokenDto>(TokenJson);
        
        //Set token so can use through out class
                _tokenDTO.AccessToken = TokenDTO.AccessToken;

        }


        [Fact]
        public async Task CallAPIEndPoint1()
        {
        //re-use AccessToken
        _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _tokenDTO.AccessToken);
        var api1 = await _client.GetAsync("api/Car/CarNames");
    }
    [Fact]
        public async Task CallAPIEndPoint2()
        {
        //re-use AccessToken
        _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _tokenDTO.AccessToken);
        var api2 = await _client.GetAsync("api/Car/CarTypes");
    }
    [Fact]
        public async Task CallAPIEndPoint2()
        {
        //re-use AccessToken
        _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _tokenDTO.AccessToken);
        var api3 = await _client.GetAsync("api/Car/CarColour");
    }

}

So I could successfully call the controller functions:

[Authorize]
    [HttpPost("CarNames")
    public async Task<IActionResult> CarNames()
    {
        try
        {
            //do something
        }
        catch (Exception ex)
        {
        }
}

This all works great my Q is how can I set TokenDTO.AccessToken to a global variable which can be accessed across all test classes for the duration of the testing?

Thank you for any response

1

There are 1 best solutions below

0
quyentho On

You are one step in the right direction by using IClassFixture. Here is an example of how to create the Fixture class to get your token.

public class TokenFixture
{
    public TokenFixture()
    {
        Token = GetToken().Result;
    }

    private async Task<string> GetToken()
    {
        // replace with actual token requesting logic
        var token = await Task.FromResult("Token");

        return token;
    }

    public string Token { get; set; }
}

Then you can use it in your GetTokenControllerTest.cs:

public class ControllerTests: IClassFixture<TokenFixture>
{
    TokenFixture fixture;

    public ControllerTests(TokenFixture fixture)
    {

        this.fixture = fixture;
    }

    [Fact]
    public void Test1()
    {
        Assert.Equal("Token", fixture.Token);
    }
    [Fact]
    public void Test2()
    {
        Assert.Equal("Token", fixture.Token);
    }
}