ASP.Net Тестирование интеграции Core xUnit при включении двухфакторной аутентификации

#unit-testing #asp.net-core #asp.net-identity

Вопрос:

Я разрабатываю веб-приложение Angular с использованием ASP.Net Ядро 3.1 для API.

До сих пор я написал несколько модульных тестов интеграции с использованием пользовательского веб-приложения для создания тестового сервера.

Все тесты используют HttpClient для получения и отправки сообщений в API, работающий в пользовательском веб-приложении. Большинство из этих тестов сначала выполняют вход в систему для получения маркера, который будет использоваться для последующих запросов.

Я хотел бы добавить в приложение двухфакторную аутентификацию, но это неизбежно нарушит любые тесты, так как они не смогут получить шестизначный код, который будет отправлен по электронной почте.

Вот как в настоящее время выглядит тест без внедрения MFA. Есть ли способ дать тесту код MFA, чтобы он мог продолжать выполнять тесты?

Нужно ли мне просто ввести пользователя, у которого не включен MFA? Я на самом деле хочу, чтобы у всех пользователей был включен MFA в производстве.

Большое спасибо

 using Xunit;
using System.Threading.Tasks;
using MyCompany.ViewModels.Authentication;
using MyCompany.StaffPortal.Tests.Shared;
using StaffPortal;
using Newtonsoft.Json;
using MyCompany.ServiceA.ViewModels;
using System.Collections.Generic;
using System.Net.Http;

namespace MyCompany.Tests.StaffPortal.ServiceA
{
    public class ExtensionsControllerTests : TestBase
    {
        public ExtensionsControllerTests(CustomWebApplicationFactory<Startup> factory) : base(factory)
        {
        }

        [Fact]
        public async Task Test_GetExtensions()
        {
            //This line creates a new "web browser" and uses the login details provided to obtain and set up the token so that we can request information about an account.
            HttpClient httpClient = await CreateAuthenticatedHttpClient("abcltd1@MyCompany.com", "test", 1);

            //Perform any work and get the information from the API
            //Contact the API using the token so check that it works
            var getExtensionsResponse = await httpClient.GetAsync("/api/ServiceA/extensions/GetExtensions");

            //Check that the response was OK
            Assert.True(getExtensionsResponse.StatusCode == System.Net.HttpStatusCode.OK, "GetExtensions did not return an OK result.");

            //Get and Convert the Content we received into a List of ServiceAExtensionViewModel, as that is what GetExtensions sends back to the browser.
            var getExtensionsResponseContent = await getExtensionsResponse.Content.ReadAsStringAsync();
            List<ServiceAExtensionViewModel> extensionList = JsonConvert.DeserializeObject<List<ServiceAExtensionViewModel>>(getExtensionsResponseContent);


            //Check the information received matches our expectations
            Assert.True(extensionList.Count == 2);
            Assert.True(extensionList[0].PropertyA == 123);
            Assert.True(extensionList[0].PropertyB == 0161);
            Assert.True(extensionList[0].PropertyC == true);
        }
    }
}
 

Вот содержимое CreateAuthenticatedHttpClient() для справки.

 protected async Task<HttpClient> CreateAuthenticatedHttpClient(string username, string password, int companyAccountId)
        {
            var httpClient = _factory.CreateClient(
                new WebApplicationFactoryClientOptions
                {
                    AllowAutoRedirect = false
                });

            //Create the Login information to send to the server
            var loginInformation = new LoginRequestModel
            {
                Username = username,
                Password = password,
                ReturnUrl = ""
            };

            //Convert it into Json which the server will understand
            var validLoginRequestJson = ConvertToJson(loginInformation);

            //Send the Json Login information to the server, and put the response we receive into loginResponse
            //In the code below, httpClient is like a web browser. You give it the 
            var loginResponse = await httpClient.PostAsync("/api/authenticate", validLoginRequestJson);

            //Check the loginResponse was a CREATED response, which means that the token was made
            Assert.True(loginResponse.StatusCode == System.Net.HttpStatusCode.Created, "New Token was not returned.");

            //Check the response is identified as being in Json format
            Assert.Equal("application/json; charset=utf-8", loginResponse.Content.Headers.ContentType.ToString());

            //Next we have to convert the received Json information into whatever we are expecting.
            //In this case, we are expecting a AuthenticationResponseViewModel (because that's what the API sends back to the person trying to log in)
            //First we get hold of the Content (which is in Json format)
            var responseJsonString = await loginResponse.Content.ReadAsStringAsync();

            //Second we convert the Json back into a real AuthenticationResponseViewModel
            AuthenticationResponseViewModel authenticationResponseViewModel = JsonConvert.DeserializeObject<AuthenticationResponseViewModel>(responseJsonString);

            //Now we take the Token from AuthenticationResponseViewModel, and add it into the httpClient so that we can check the Token works.
            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authenticationResponseViewModel.token);

            httpClient.DefaultRequestHeaders.Add("CompanyId", companyAccountId.ToString());

            return httpClient;
        }