UnitTest на контроллере WebAPI с проверкой подлинности Windows

У меня есть API с несколькими методами. Мне нужно аутентифицировать пользователя с помощью Windows Authentication, прежде чем он попадет в любой из методов контроллера. Для этого я написал частный метод, чтобы получить UserIdentity и присвоить его частной bool переменной.

Каждый из методов контроллера сначала проверяет логическое значение, чтобы подтвердить пользователя, и, если это не удается, возвращает 401 обратно во внешний интерфейс.

Во время написания модульного теста для методов контроллера я не уверен, как смоделировать UserIdentity или мне следует обновить контроллер таким образом, чтобы разрешить тестирование UserIdentity

Контроллер:

public class DefaultController : ApiController
{
  private bool isUsrAuthenticated;

  public DefaultController()
  {
    AuthenticateUser();
  }

  private void AuthenticateUser()
  {
    isUsrAuthenticated = User.Identity.IsAuthenticated;
  }

  [HttpGet]
  public IHttpActionResult GetProducts()
  {
    if (isUsrAuthenticated) { // do something }
    else { // throw 401 }
  }

  [HttpPost]
  public IHttpActionResult Update()
  {
    if (isUsrAuthenticated) { // do something }
    else { // throw 401 }
  }
}

Результаты модульного теста всегда возвращают 401.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
228
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во время выполнения свойство ApiController.User устанавливается после вызова конструктора контроллера. Это означало бы, что ваш текущий поток вызова его в конструкторе, например

public DefaultController() {
    AuthenticateUser();
}

имеет недостатки и не обеспечивает ожидаемого поведения.

Давайте сначала исправим код, а затем посмотрим на модульный тест.

Вместо этого используйте свойство, например

private bool IsUserAuthenticated {
    get {
        return User.Identity.IsAuthenticated;
    }
}

и соответствующим образом рефакторить код

public class DefaultController : ApiController {

    private bool IsUserAuthenticated {
        get {
            return User.Identity.IsAuthenticated;
        }
    }

    [HttpGet]
    public IHttpActionResult GetProducts() {
        if (IsUserAuthenticated) { // do something }
        else { // throw 401 }
    }

    [HttpPost]
    public IHttpActionResult Update() {
        if (IsUserAuthenticated) { // do something }
        else { // throw 401 }
    }

    //...

}

Теперь для тестирования ApiController свойство User можно установить при организации модульного теста, чтобы тест выполнялся должным образом.

Например

[TestMethod()]
public void DefaultController_Should_GetProducts() {
    //Arrange
    var username = "name_here";
    var userId = 2;

    var identity = new GenericIdentity(username, "");
    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId.ToString()));
    identity.AddClaim(new Claim(ClaimTypes.Name, username));

    var principal = new GenericPrincipal(identity, roles: new string[] { });
    var user = new ClaimsPrincipal(principal);

    var controller = new DefaultController() {
        User = user //<-- Set the User on the controller directly
    };

    //Act
    var actionResult = controller.GetProducts();

    //Assert
    //...
}

Другие вопросы по теме