Тестирование действия контроллера, использующего User.Identity.Name

У меня есть действие, которое полагается на User.Identity.Name, чтобы получить имя пользователя текущего пользователя, чтобы получить список его заказов:

public ActionResult XLineas()
    {
        ViewData["Filtre"] = _options.Filtre;
        ViewData["NomesPendents"] = _options.NomesPendents;
        return View(_repository.ObteLiniesPedido(User.Identity.Name,_options.Filtre,_options.NomesPendents));
    }

Теперь я пытаюсь написать модульные тесты для этого, но я застрял на том, как предоставить Mock для User.Identity.Name. Если я запускаю свой тест так, как он у меня есть (без макета для пользователя...), я получаю исключение Null...

Какой правильный подход для этого? Я думаю, что мой код действия не подходит для модульного тестирования.


person Carles Company    schedule 07.09.2009    source источник


Ответы (2)


Лучшим способом сделать это было бы передать аргумент string userName (или аргумент IPrincipal user, если вам нужно больше информации, чем просто имя) методу ActionMethod, который вы «вставляете» в обычный запрос, используя атрибут ActionFilterAttribute. Когда вы тестируете его, вы просто предоставляете свой собственный фиктивный объект, так как код фильтра действий не будет работать (в большинстве случаев - есть способы, если вы специально хотите...)

Кази Манзур Рашид подробно описывает это в пункте 7 в отличный пост в блоге.

person Tomas Aschan    schedule 07.09.2009
comment
Здорово. Мне нужно больше изучить ActionFilters... Спасибо. - person Carles Company; 07.09.2009
comment
Я часто издеваюсь над IPrincipal для своих тестов. Это позволяет мне проверять информацию о пользователе (имя пользователя), а также авторизацию (User.Identity.IsInRole). - person mberube.Net; 08.10.2009
comment
Я тоже. С другой стороны, издевательство над IPrincipal только для получения доступа к имени пользователя текущего пользователя — и ничего — на грани излишества... :) - person Tomas Aschan; 08.10.2009
comment
При передаче объекта IPrincipal или IIdentity вам потребуется использовать интерфейс и оболочку. Простое использование ActionFilter приведет к ошибке, говорящей о том, что вы не можете реализовать интерфейс. - person Cavyn VonDeylen; 15.01.2013
comment
Статья Кази Манзура Рашида дает прекрасную отправную точку. Я предпочитаю модифицировать код, чтобы немедленно выдавать исключение InvalidOperationException, если пользователь не авторизован. Также обратите внимание, что вам, вероятно, все равно следует писать модульные тесты для вашего ActionFilterAttribute, и вам все равно придется издеваться над этими вещами хотя бы один раз. - person jakejgordon; 07.07.2014
comment
@rob: Спасибо, что поставили меня в известность. Пост довольно старый (он не был новым, когда я написал этот ответ более 7 лет назад...), и я также не могу найти его в архиве. Однако с тех пор в среде ASP.NET многое произошло, так что могу поспорить, что есть и другие статьи, описывающие более новые решения подобных проблем. - person Tomas Aschan; 28.10.2016
comment
@rob: я нашел статью в машине обратного пути, но ссылка обновлена ​​:D - person Tomas Aschan; 28.10.2016

Вы можете использовать этот код

public SomeController CreateControllerForUser(string userName) 
{
    var mock = new Mock<ControllerContext>();
    mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
    mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

    var controller = new SomeController();
    controller.ControllerContext = mock.Object;

    return controller;
}

Он использует фреймворк для имитации Moq, но вы можете использовать все, что захотите.

person Sly    schedule 19.07.2011
comment
Для всех, кому интересно, как и мне: в этом примере кода используется Moq. - person Joel Malone; 26.03.2013
comment
В WebAPI мне понравилось MyController controller = new MyController(); controller.User = new GenericPrincipal(new GenericIdentity(username, "Passport"), new[] { "tester" }); - person Ravi; 22.04.2015
comment
@ Рави Как? Controller.User не устанавливается(хотя за последние 2,5 года могло что-то измениться) - person Wolfzoon; 08.08.2017
comment
@Wolfzoon Я должен быть честным. Я больше не использую DotNet. Не помню, чтобы ответить на это :-). Простите меня. - person Ravi; 09.08.2017