Мок HttpRequest в контроллере ядра ASP.NET

Я создаю веб-API в ASP.NET Core и хочу провести модульное тестирование контроллеров.

Я ввожу интерфейс для доступа к данным, над которым я легко могу имитировать. Но контроллер должен проверить заголовки в запросе на токен, и этот запрос, похоже, не существует, когда я просто создаю экземпляр контроллера сам, и он также доступен только для получения, поэтому я даже не могу его вручную установить. Я нашел множество примеров имитации ApiController, но это не ядро ​​.NET. Также много руководств и примеров того, как проводить модульное тестирование контроллеров ядра .NET, но ни один из них на самом деле не использовал HttpRequest.

Я построил MCVE, чтобы продемонстрировать это:

[Produces("application/json")]
[Route("api/Players")]
public class PlayersController : Controller
{
    private IAccessor accessor;

    public PlayersController(IAccessor ac = null):base()
    {
        accessor = ac ?? AccessorFactory.GetAccessor();
    }

    /// <summary>
    /// Get all players. Must be logged in.
    /// </summary>
    /// <returns>Ok or Unauthorized.</returns>
    [HttpGet]
    public IActionResult Get()
    {
        Player client = accessor.GetLoggedInPlayer(Request.Headers["token"]); // NRE here because Request is null
        if (client == null) return Unauthorized();
        return Ok(accessor.GetAllPlayers());

    }
}    

Я использую Moq и MSTest в своем тестовом проекте и внедряю имитацию IAccessor. Как мне ввести запрос или инициализировать его с помощью контроллера? Думаю, моим последним средством было бы размышление, но я действительно хочу избежать этого.

Возможный дубликат Mock HttpContext для модульного тестирования контроллера MVC ядра .NET?

Michael Freidgeim 16.08.2019 10:16
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
32
1
33 225
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

Вы можете попробовать издеваться над HttpContext и предоставить это контроллеру или просто использовать DefaultHttpContext, предоставленный фреймворком.

//Arrange
var mockedAccessor = new Mock<IAccessor>();
//...setup mockedAccessor behavior

//...

var httpContext = new DefaultHttpContext(); // or mock a `HttpContext`
httpContext.Request.Headers["token"] = "fake_token_here"; //Set header
 //Controller needs a controller context 
var controllerContext = new ControllerContext() {
    HttpContext = httpContext,
};
//assign context to controller
var controller = new PlayersController (mockedAccessor.Object){
    ControllerContext = controllerContext,
};

//Act
var result = controller.Get();

//...

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

@Nikosi можешь проверить это ссылка на сайт

Zaker 04.06.2020 10:07

Я также слышал, что http-контекст не следует издеваться над тестами. Поэтому я хотел бы подчеркнуть предложение использовать DefaultHttpContext вместо того, чтобы пытаться издеваться над ним.

Ravior 11.08.2020 09:39

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