В предыдущих версиях вы могли бы установить User
непосредственно на контроллере, который сделал для некоторых очень простых модульных тестов.
Если вы посмотрите на исходный код для ControllerBase, вы заметите, что User
извлечен из HttpContext
.
/// <summary>
/// Gets or sets the <see cref="ClaimsPrincipal"/> for user associated with the executing action.
/// </summary>
public ClaimsPrincipal User
{
get
{
return HttpContext?.User;
}
}
и контроллер обращается к HttpContext
через ControllerContext
/// <summary>
/// Gets the <see cref="Http.HttpContext"/> for the executing action.
/// </summary>
public HttpContext HttpContext
{
get
{
return ControllerContext.HttpContext;
}
}
Вы заметите, что эти два считываются только свойства. Хорошей новостью является то, что свойство ControllerContext
позволяет установить его значение так, чтобы оно было вашим.
Итак, цель - добраться до этого объекта. В Core HttpContext
является абстрактным, поэтому намного проще насмехаться.
Предполагая контроллер как
public class MyController : Controller {
IMyContext _context;
public MyController(IMyContext context) {
_context = context;
}
public IActionResult Index() {
SettingsViewModel svm = _context.MySettings(User.Identity.Name);
return View(svm);
}
//...other code removed for brevity
}
Использование Moq, тест может выглядеть следующим образом
public void Given_User_Index_Should_Return_ViewResult_With_Model() {
//Arrange
var username = "FakeUserName";
var identity = new GenericIdentity(username, "");
var mockPrincipal = new Mock<IPrincipal>();
mockPrincipal.Setup(x => x.Identity).Returns(identity);
mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);
var mockHttpContext = new Mock<HttpContext>();
mockHttpContext.Setup(m => m.User).Returns(mockPrincipal.Object);
var model = new SettingsViewModel() {
//...other code removed for brevity
};
var mockContext = new Mock<IMyContext>();
mockContext.Setup(m => m.MySettings(username)).Returns(model);
var controller = new MyController(mockContext.Object) {
ControllerContext = new ControllerContext {
HttpContext = mockHttpContext.Object
}
};
//Act
var viewResult = controller.Index() as ViewResult;
//Assert
Assert.IsNotNull(viewResult);
Assert.IsNotNull(viewResult.Model);
Assert.AreEqual(model, viewResult.Model);
}
В моем случае это было 'new Claim (ClaimTypes.Name," 1 ")' для соответствия использованию контроллера 'user.Identity.Name'; но в противном случае это именно то, чего я пытался достичь ... Danke schon! – Felix
После бесчисленных часов поиска это было сообщение, которое, наконец, привело меня в квадрат. В моем основном проекте контроллера проекта я использовал «User.FindFirstValue (ClaimTypes.NameIdentifier)», чтобы установить userId для объекта, который я создавал, и терпел неудачу, потому что основной был null. Это фиксировало это для меня. Спасибо за отличный ответ! –