C# ASP.NET MVC:我正在尝试编写一个测试来查看新用户注册是否成功

C# ASP.NET MVC : I'm trying to write a test to see if registering a new user succeeds

我有一个带有基本 Register 页面的 ASP.NET MVC 应用程序。这是注册新用户的具体功能。

Register.cshtml.cs:

public async Task<IActionResult> OnPostAsync()
{
        var returnUrl = Url.Content("~/Home/PostRegister");

        if (ModelState.IsValid)
        {
            var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
            var result = await _userManager.CreateAsync(user, Input.Password);
            if (result.Succeeded)
            {
                _logger.LogInformation("User created a new account with password.");

                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { userId = user.Id, code = code },
                    protocol: Request.Scheme);

                await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                    $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }

            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        // If we got this far, something failed, redisplay form
        return Page();
}

这是我在集成测试中为它编写的测试:

[Fact]
public async Task DoesRegisterSucceed()
{
        // Arrange
        var client = _factory.CreateClient(
            new WebApplicationFactoryClientOptions
            {
                AllowAutoRedirect = false
            });
        
        var postRequest = new HttpRequestMessage(HttpMethod.Post, "/Identity/Account/Register");
        var formModel = new Dictionary<string, string>
        {
            { "Email", "test@example.com" },
            { "Password", "pas3w0!rRd" },
            { "ConfirmPassword", "pas3w0!rRd" },
        };

        postRequest.Content = new FormUrlEncodedContent(formModel);
        var response = await client.SendAsync(postRequest);

        response.EnsureSuccessStatusCode();

        //var responseString = await response.Content.ReadAsStringAsync();
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

我在 运行 测试时遇到此错误。

Failed amaranth.Tests.AuthTests.Get_ClaimAdminIsReturnedForFirstRegistered [505 ms]
Error Message:
System.Net.Http.HttpRequestException : Response status code does not indicate success: 400 (Bad Request).

Stack Trace:

at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at amaranth.Tests.AuthTests.Get_ClaimAdminIsReturnedForFirstRegistered() in /path/to/dir/amaranth.Tests/IntegrationTests/AuthTests.cs:line 102
--- End of stack trace from previous location ---

如何进行此测试或编写确保注册成功的新测试?

更新
如果相关,这是我正在使用的 CustomWebApplicationFactory.cs 文件:

using System;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using amaranth.Data;

namespace amaranth.Tests
{
    #region snippet1
    public class CustomWebApplicationFactory<TStartup>
        : WebApplicationFactory<TStartup> where TStartup: class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                var descriptor = services.SingleOrDefault(
                    d => d.ServiceType ==
                        typeof(DbContextOptions<ApplicationDbContext>));

                services.Remove(descriptor);

                services.AddDbContext<ApplicationDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryDbForTesting");
                });

                var sp = services.BuildServiceProvider();

                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<ApplicationDbContext>();
                    var logger = scopedServices
                        .GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                    db.Database.EnsureCreated();
                }
            });
        }
    }
    #endregion
}

测试失败,因为您没有在 POST 中包含防伪 cookie 和验证令牌,因此出现 400 状态代码。来自 this page in the docs:

Any POST request to the SUT must satisfy the antiforgery check that's automatically made by the app's data protection antiforgery system. In order to arrange for a test's POST request, the test app must:

  1. Make a request for the page.
  2. Parse the antiforgery cookie and request validation token from the response.
  3. Make the POST request with the antiforgery cookie and request validation token in place.