Как смоделировать HttpContext для доступа к методу расширения IIdentity? - PullRequest
0 голосов
/ 25 февраля 2019

В моем проекте MVC я создаю модульные тесты для контроллера, возвращающего представление.

Этот результат действия контроллера создает модель представления, и конструктор этой модели вызова вызывает

HttpContext.Current.User.Identity.NameWithoutDomain().ToUpper();

ГдеNameWithoutDomain - это метод расширения IIdentity.

Всякий раз, когда я запускаю его, я получаю «объект не может быть найден», и мне любопытно, как я могу соответствующим образом смоделировать это для модульного тестирования?

Метод расширения:

public static class SystemWebExtension
{
    public static string NameWithoutDomain(this IIdentity identity)
    {
        return identity.Name.Split('\\').Last();
    }
}

Конструктор модели:

public Model()
{
    this.PreparedByUser = HttpContext.Current.User.Identity.NameWithoutDomain().ToUpper();
    this.AuthorizedBy = true;
    this.AuthorizedByUser = HttpContext.Current.User.Identity.NameWithoutDomain().ToUpper();
    this.IssueCredit = true;
    this.CreateUser = string.IsNullOrEmpty(this.CreateUser) ? Environment.UserName.ToLower() : this.CreateUser;
    this.CreateDate = this.CreateDate.HasValue ? this.CreateDate : DateTime.Now;
    this.UpdateUser = string.IsNullOrEmpty(this.CreateUser) ? null : Environment.UserName.ToLower();
    this.UpdateDate = this.CreateDate.HasValue ? DateTime.Now : (DateTime?) null;
}

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

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

Чтобы убедиться, что NameWithoutDomain возвращает то, что вы хотите, выможет смоделировать IIdentity и заставить его вернуть желаемое имя пользователя, например:

var identityMock = new Mock<IIdentity>();
identityMock.SetupGet(x => x.Name).Returns("UsernameWithoutDomain");

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

Что касается HttpContext, вы можете просто создать его экземпляр перед созданием контроллера и передать ему проверенный IIdentity, например, так ( протестирован сWebAPI2 ):

var identityMock = new Mock<IIdentity>();
identityMock.SetupGet(x => x.Name).Returns("UsernameWithoutDomain");

HttpContext.Current =
    new HttpContext(new HttpRequest(null, "http://test.com", null), new HttpResponse(null))
    {
        User = new GenericPrincipal(identityMock.Object, new[] {"Role1"})
    };

var myController = new AccountController();

Затем, когда вы создаете экземпляр вашего контроллера для тестирования, HttpContext.Current.User.Identity.Name вернет UsernameWithoutDomain.Удачного тестирования!: -)

0 голосов
/ 25 февраля 2019

Избегайте подключения к HttpContext, так как оно недоступно при модульном тестировании.

Вы должны явно ввести необходимые значения в модель

public Model(IIdentity identity) {
    this.PreparedByUser = identity.NameWithoutDomain().ToUpper();
    this.AuthorizedBy = true;
    this.AuthorizedByUser = identity.NameWithoutDomain().ToUpper();
    this.IssueCredit = true;
    this.CreateUser = string.IsNullOrEmpty(this.CreateUser) ? Environment.UserName.ToLower() : this.CreateUser;
    this.CreateDate = this.CreateDate.HasValue ? this.CreateDate : DateTime.Now;
    this.UpdateUser = string.IsNullOrEmpty(this.CreateUser) ? null : Environment.UserName.ToLower();
    this.UpdateDate = this.CreateDate.HasValue ? DateTime.Now : (DateTime?) null;
}

Поскольку при использовании контроллера у вас будет доступ к необходимой информации в его свойствах

//...

var model = new Model(this.User.Identity);

return View(model);

А при тестировании вы можете настроить контроллер через контекст контроллера

//...
var username = "some username here"
var identity = new GenericIdentity(username, "");
identity.AddClaim(new Claim(ClaimTypes.Name, username));
var principal = new GenericPrincipal(identity, roles: new string[] { });
var user = new ClaimsPrincipal(principal);

var context = new Mock<HttpContextBase>();
context.Setup(_ => _.User).Returns(user);

//...

controller.ControllerContext = new ControllerContext(context.Object, new RouteData(),  controller );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...