单元测试 - 如何将控制器用户设置为通用主体对象
Unit Test - How to set controller user to Generic Principal object
已更新完整解决方案:
我要测试的 WebApi 控制器方法:
using Microsoft.AspNet.Identity;
using System.Web.Http;
[Authorize]
public class GigsController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public GigsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpDelete]
public IHttpActionResult Cancel(int id)
{
var userId = User.Identity.GetUserId();
var gig = _unitOfWork.Gigs.GetGigWithAttendees(id);
if (gig.IsCanceled)
return NotFound();
if (gig.ArtistId != userId)
return Unauthorized();
gig.Cancel();
_unitOfWork.Complete();
return Ok();
}
}
单元测试class:
[TestClass]
public class GigsControllerTests
{
private GigsController _controller;
public GigsControllerTests()
{
var identity = new GenericIdentity("user1@domain.com");
identity.AddClaim(
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "user1@domain.com"));
identity.AddClaim(
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "1"));
var principal = new GenericPrincipal(identity, null);
var mockUoW = new Mock<IUnitOfWork>();
_controller = new GigsController(mockUoW.Object);
_controller.User = principal;
}
我收到以下错误:
Error CS0200 Property or indexer 'ApiController.User' cannot be
assigned to -- it is read only
https://i.stack.imgur.com/YDQJS.png
改为设置执行线程的 CurrentPrincipal
Thread.CurrentPrincipal = principal;
可以通过ControllerContext
分配
var user = new ClaimsPrincipal();
var context = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = user
}
};
controllerUnderTest.ControllerContext = context;
我在遵循 Moshi 的教程时 运行 遇到了同样的问题,这让我困扰了好几个小时才终于能够解决这个问题。
最终,为我解决此问题的是更改我的 using 语句:
使用 GigHub.Controllers;
至
使用 GigHub.Controllers.Api;
您的 GigsController _controller 指向控制器本身,而不是 Api控制器。我有点希望 Moshi 在他的 API classes 的名字中加上 "Api" 这样你就会知道你是在看纯控制器还是 API 版本控制器无需检查名称空间或转到对象上的定义。
您是对的,控制器 class 的用户 属性 确实只有一个 Get。
public abstract class Controller : ControllerBase, IActionFilter,
IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter,
IResultFilter, IAsyncController, IController, IAsyncManagerContainer
{
public IPrincipal User { get; }
}
Api控制器 class 的用户 属性 但是同时具有 Get 和 Set。
public abstract class ApiController : IHttpController, IDisposable
{
public IPrincipal User { get; set; }
}
希望这也是您遇到的问题,希望对您有所帮助!
干杯!
当我试图在控制器中模拟用户而不是 controller.api 时遇到了这个 post…并且挣扎。
无论如何,方法是用模拟对象覆盖控制器中的 ControllerContext,并将模拟对象设置为 return 您希望模拟的用户。
var user = CreateLoggedInUser(targetUserID);
mockControllerContext = new Mock<ControllerContext>();
mockControllerContext.Setup(o => o.HttpContext.User).Returns(user);
myCaseController.ControllerContext = mockControllerContext.Object;
和
private ClaimsPrincipal CreateLoggedInUser(int userID)
{
GenericIdentity myIdentity = new GenericIdentity("apiTestUser");
myIdentity.AddClaims(new List<Claim> {
new Claim(ClaimTypes.Sid, userID.ToString()),
});
return new ClaimsPrincipal(myIdentity);
}
已更新完整解决方案:
我要测试的 WebApi 控制器方法:
using Microsoft.AspNet.Identity;
using System.Web.Http;
[Authorize]
public class GigsController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public GigsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpDelete]
public IHttpActionResult Cancel(int id)
{
var userId = User.Identity.GetUserId();
var gig = _unitOfWork.Gigs.GetGigWithAttendees(id);
if (gig.IsCanceled)
return NotFound();
if (gig.ArtistId != userId)
return Unauthorized();
gig.Cancel();
_unitOfWork.Complete();
return Ok();
}
}
单元测试class:
[TestClass]
public class GigsControllerTests
{
private GigsController _controller;
public GigsControllerTests()
{
var identity = new GenericIdentity("user1@domain.com");
identity.AddClaim(
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "user1@domain.com"));
identity.AddClaim(
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "1"));
var principal = new GenericPrincipal(identity, null);
var mockUoW = new Mock<IUnitOfWork>();
_controller = new GigsController(mockUoW.Object);
_controller.User = principal;
}
我收到以下错误:
Error CS0200 Property or indexer 'ApiController.User' cannot be assigned to -- it is read only
https://i.stack.imgur.com/YDQJS.png
改为设置执行线程的 CurrentPrincipal
Thread.CurrentPrincipal = principal;
可以通过ControllerContext
var user = new ClaimsPrincipal();
var context = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = user
}
};
controllerUnderTest.ControllerContext = context;
我在遵循 Moshi 的教程时 运行 遇到了同样的问题,这让我困扰了好几个小时才终于能够解决这个问题。
最终,为我解决此问题的是更改我的 using 语句:
使用 GigHub.Controllers;
至
使用 GigHub.Controllers.Api;
您的 GigsController _controller 指向控制器本身,而不是 Api控制器。我有点希望 Moshi 在他的 API classes 的名字中加上 "Api" 这样你就会知道你是在看纯控制器还是 API 版本控制器无需检查名称空间或转到对象上的定义。
您是对的,控制器 class 的用户 属性 确实只有一个 Get。
public abstract class Controller : ControllerBase, IActionFilter,
IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter,
IResultFilter, IAsyncController, IController, IAsyncManagerContainer
{
public IPrincipal User { get; }
}
Api控制器 class 的用户 属性 但是同时具有 Get 和 Set。
public abstract class ApiController : IHttpController, IDisposable
{
public IPrincipal User { get; set; }
}
希望这也是您遇到的问题,希望对您有所帮助!
干杯!
当我试图在控制器中模拟用户而不是 controller.api 时遇到了这个 post…并且挣扎。 无论如何,方法是用模拟对象覆盖控制器中的 ControllerContext,并将模拟对象设置为 return 您希望模拟的用户。
var user = CreateLoggedInUser(targetUserID);
mockControllerContext = new Mock<ControllerContext>();
mockControllerContext.Setup(o => o.HttpContext.User).Returns(user);
myCaseController.ControllerContext = mockControllerContext.Object;
和
private ClaimsPrincipal CreateLoggedInUser(int userID)
{
GenericIdentity myIdentity = new GenericIdentity("apiTestUser");
myIdentity.AddClaims(new List<Claim> {
new Claim(ClaimTypes.Sid, userID.ToString()),
});
return new ClaimsPrincipal(myIdentity);
}