首页 > 解决方案 > 启用两因素身份验证时的 ASP.Net Core XUnit 集成测试

问题描述

我正在为 API 使用 ASP.Net Core 3.1 开发一个 Angular Web 应用程序。

到目前为止,我已经使用 Custom WebApplicationFactory 编写了一些集成单元测试来创建测试服务器。

所有测试都使用 HttpClient 对在 Custom WebApplicationFactory 下运行的 API 进行 GET 和 POST。大多数这些测试最初执行登录以获得用于后续请求的令牌。

我想在应用程序中添加两因素身份验证,但这将不可避免地破坏任何测试,因为他们无法获取将通过电子邮件发送的六位数代码。

这是当前未实施 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;
        }

标签: unit-testingasp.net-coreasp.net-identity

解决方案


推荐阅读