Пользователь ClaimsIdentity не распознается как вошедший в систему во время теста - PullRequest
0 голосов
/ 02 октября 2018

Я пытаюсь установить модульное тестирование в новом проекте, над которым я работаю.Я использую ASP.NET Boilerplate (.NET Core, многостраничное приложение) с предварительно созданной аутентификацией в качестве отправной точки.Поскольку Web.Tests не включен в этот шаблон , я пытаюсь создать свой собственный, используя то, что было предоставлено в шаблоне ASP.NET Core .Я смог установить класс Startup, который использует InMemoryDatabase для тестирования.Однако самый базовый из тестов не проходит.Я застреваю при наличии тестового пользователя, который полностью аутентифицирован и распознается как «авторизованный».Тестируемый код выглядит так:

[AbpMvcAuthorize]
public class HomeController : ProjectControllerBase
{
    public ActionResult Index()
    {
        return View();
    }
}

Тест написан так:

[Fact]
public async Task Index_Test()
{            
    // Added as part of suggestions made by 'https://medium.com/@zbartl/authentication-and-asp-net-core-integration-testing-using-testserver-15d47b03045a'
    Client.DefaultRequestHeaders.Add("my-name", "admin");
    Client.DefaultRequestHeaders.Add("my-id", "2");

    // Act
    var response = await GetResponseAsStringAsync(
        GetUrl<HomeController>(nameof(HomeController.Index))
    );

    // Assert
    response.ShouldNotBeNullOrEmpty();
}

Блог, на который ссылается здесь , позволил мне предоставить ClaimsPrincipalс ClaimsIdentity с использованием класса Middleware.Класс промежуточного программного обеспечения выглядит следующим образом:

public class TestAuthenticationMiddleware
{
    private readonly RequestDelegate _next;

    public TestAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemas)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Headers.Keys.Contains("my-name"))
        {
            if (context.Request.Headers["my-name"].First().Equals("admin"))
            {
                ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
                    {
                        new Claim(ClaimTypes.Name, "admin"),
                        new Claim(ClaimTypes.NameIdentifier, context.Request.Headers["my-id"].First()),
                        new Claim(ClaimTypes.Role, "Admin"),
                        new Claim("http://www.aspnetboilerplate.com/identity/claims/tenantId", "1", "int"),
                        new Claim("AspNet.Identity.SecurityStamp", Guid.NewGuid().ToString())

                    },
                    "Identity.Application");

                ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
                context.User = principal;
                await context.SignInAsync("Identity.Application", principal);
            }
        }

        await _next(context);
    }
}

Итак, то, что я получаю, когда я запускаю тест, является неудачным тестом.

Shouldly.ShouldAssertException : response.StatusCode
    should be
HttpStatusCode.OK
    but was HttpStatusCode.Redirect

Я думаю, что мы получаемзастрял в [AbpMvcAuthorize] функциональности и перенаправляется на страницу входа.Если я удаляю AbpMvcAuthorize из контроллера, то я получаю другое состояние отказа.Я получаю нулевую ссылку.View пытается выполнить рендеринг и терпит неудачу в последующей модели представления, когда вызывается GetShownLoginName():

public class SideBarUserAreaViewModel
{
    public GetCurrentLoginInformationsOutput LoginInformations { get; set; }

    public bool IsMultiTenancyEnabled { get; set; }

    public string GetShownLoginName()
    {
        var userName = "<span id=\"HeaderCurrentUserName\">" + LoginInformations.User.UserName + "</span>";

        if (!IsMultiTenancyEnabled)
        {
            return userName;
        }

        return LoginInformations.Tenant == null
            ? ".\\" + userName
            : LoginInformations.Tenant.TenancyName + "\\" + userName;
    }
}

Я хочу иметь возможность проверить логику моего контроллера, чтобы убедиться, что изменения в представлениях,изменения в просмотре моделей и изменения в сервисах не приводят к ошибкам загрузки страницы.Есть ли способ, кроме создания экземпляров UserManager, LogInManager и SignInManager в моем классе TestBase и программной регистрации пользователя?

1 Ответ

0 голосов
/ 05 октября 2018

Задача

  1. Ваш MyProjectWebTestBase наследует AbpAspNetCoreIntegratedTestBase<TStartup>.
  2. AbpAspNetCoreIntegratedTestBase<TStartup> использует TestAbpSession.
  3. TestAbpSession игнорирует претензии.

Решение

  1. Реализация MyTestAbpSession, которая возвращается к ClaimsAbpSession.

    public class MyTestAbpSession : TestAbpSession
    {
        public ClaimsAbpSession ClaimsAbpSession { get; set; }
    
        public MyTestAbpSession(IMultiTenancyConfig multiTenancy,
            IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider,
            ITenantResolver tenantResolver)
            : base(multiTenancy, sessionOverrideScopeProvider, tenantResolver)
        {
        }
    
        public override long? UserId
        {
            get => base.UserId ?? ClaimsAbpSession.UserId; // Fallback
            set => base.UserId = value;
        }
    }
    
  2. Зарегистрируйте его в PreInitialize методе вашего MyProjectWebTestModule.

    public override void PreInitialize()
    {
        // ...
    
        IocManager.IocContainer.Register(
            Component.For<IAbpSession, TestAbpSession>()
                .ImplementedBy<MyTestAbpSession>()
                .LifestyleSingleton()
                .IsDefault()
            );
    }
    
...