W poprzednich wersjach mogłeś ustawić User
bezpośrednio na sterowniku, co sprawiło, dla niektórych bardzo prostych testów jednostkowych.
Jeśli spojrzysz na jego kod źródłowy dla ControllerBase, zauważysz, że User
jest wyodrębniony z HttpContext
.
/// <summary>
/// Gets or sets the <see cref="ClaimsPrincipal"/> for user associated with the executing action.
/// </summary>
public ClaimsPrincipal User
{
get
{
return HttpContext?.User;
}
}
a kontroler uzyskuje dostęp do HttpContext
poprzez ControllerContext
/// <summary>
/// Gets the <see cref="Http.HttpContext"/> for the executing action.
/// </summary>
public HttpContext HttpContext
{
get
{
return ControllerContext.HttpContext;
}
}
Można zauważyć, że te dwa są tylko do odczytu właściwości. Dobrą wiadomością jest to, że właściwość ControllerContext
pozwala na ustawienie jej wartości tak, aby była dostępna.
Celem jest uzyskanie tego obiektu. W rdzeniu HttpContext
jest abstraktem, więc o wiele łatwiej jest udawać.
Zakładając kontroler jak
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
}
Korzystanie Min, test mógłby wyglądać następująco
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);
}
W moim przypadku było to 'nowe żądanie (ClaimTypes.Name," 1 ")', aby dopasować użycie kontrolera 'user.Identity.Name'; ale poza tym dokładnie to chciałem osiągnąć ... Danke schon! – Felix
Po niezliczonych godzinach szukanie tego było postem, które w końcu doprowadziło mnie do kwadratu. W mojej głównej wersji 2.0 kontrolera projektu używałem 'User.FindFirstValue (ClaimTypes.NameIdentifier);' do ustawiania ID użytkownika na obiekcie, który tworzyłem i zawodziło, ponieważ element główny miał wartość NULL. Naprawiono to dla mnie. Dzięki za wspaniałą odpowiedź! –