У приложения ASP.NET-MVC + ASP.NET-WebAPI2 + ASP.NET-Identity 1
есть api-метод Get
:
[Route("api/accounts")]
[HttpGet]
public HttpResponseMessage Get()
{
var user = _dbContext.Users.Find(User.Identity.GetUserId());
if(user.Roles.Count > 0)
{
var userRoles = user.Roles.Select(x => x.Role.Name);
var model = new ApiViewModel
{
UserName = User.Identity.Name,
UserRoleNames = userRoles
};
return Request.CreateResponse(HttpStatusCode.OK, model);
}
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "The user has no one role");
}
Хочу протестировать этот метод. Для данного метода необходимо, чтобы в контексте запроса был авторизованный пользователь. Я решил попробовать замокать вызов User.Identity.GetUserId()
- получить Id существующего в БД пользователя:
[TestMethod()]
public void GetTest()
{
//Arrange
var mockPrincipal = new Mock<IPrincipal>();
var mockIdentity = new Mock<IIdentity>();
mockPrincipal.SetupGet(x => x.Identity).Returns(mockIdentity.Object);
mockIdentity.Setup(x => x.GetUserId()).Returns("5dcf65f5-2e42");
...
И в ответ получил исключение:
Expression references a method that does not belong to the mocked object: x => x.GetUserId()
Есть ли возможность замокать вызов метода расширения или есть ли другой способ передать в контекст запроса Get
авторизованного пользователя?
Обновил юнит-тест, согласно ответу @Pavel Mayorov:
[TestMethod()]
public void GetTest()
{
//Arrange
var mockIdentity = new ClaimsIdentity();
mockIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "5dcf65f5-2e42"));
var mockPrincipal = new ClaimsPrincipal(mockIdentity);
var controller = new AccountController
{
User = mockPrincipal
};
controller.User = mockPrincipal;
//Act
var result = controller.Get();
+ вызов User.Identity.GetUserId()
возвращает 5dcf65f5-2e42
что и требовалось.
- но дальше Find
(_dbContext.Users.Find(User.Identity.GetUserId())
) возвращает null
.
Почему во время теста? при передачи валидного Id
Find
вернул null
.
Этот метод ищет среди прочих утверждений (Claims) утверждение с именем ClaimTypes.NameIdentifier
. Кстати, IIdentity
- это объект-носитель данных, а не сервис, и мокать его нет смысла.
Поэтому проще всего создать новую ClaimsIdentity и добавить ей нужные утверждения:
var mockIdentity = new ClaimsIdentity();
mockIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "5dcf65f5-2e42"));
var mockPrincipal = new ClaimsPrincipal(mockIdentity);
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Ситуация такая, url который требуется выводится в DebugLog (http_response
Прошу привести пример использования RIO сокетов со стороны клиентаНапример, несколько коннектов к разным серверам
Здравствуйте! У меня есть массив объектов класса EmployerПочти у всех объектов разные значения времени (Employer
Не очень силён в async/await, не могу понять, что мне студия советует сделать