我如何模拟User.Identity.GetUserId()?
我正在尝试对我的代码进行unit testing,其中包括以下行:
UserLoginInfo userIdentity = UserManager.GetLogins(User.Identity.GetUserId()).FirstOrDefault();
因为我无法得到,我只是被困在一点上:
User.Identity.GetUserId()
返回一个值。 我在设置控制器时一直在尝试以下方法:
var mock = new Mock(); mock.Setup(p => p.HttpContext.User.Identity.GetUserId()).Returns("string");
但是它给出了“NotSupportedException未被用户代码处理”的错误。 我也尝试过以下方法:
ControllerContext controllerContext = new ControllerContext(); string username = "username"; string userid = Guid.NewGuid().ToString("N"); //could be a constant List claims = new List{ new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", username), new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userid) }; var genericIdentity = new GenericIdentity("Andrew"); genericIdentity.AddClaims(claims); var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { }); controllerContext.HttpContext.User = genericPrincipal;
基于我在stackoverflow上找到的一些代码,但这会返回相同的错误“NotSupportedException未被用户代码处理”。
任何有关我如何进行的帮助将不胜感激。 谢谢。
您无法设置GetUserId方法,因为它是一种扩展方法。 相反,您必须在用户的IIdentity属性上设置名称。 GetUserId将使用它来确定UserId。
var context = new Mock(); var mockIdentity = new Mock(); context.SetupGet(x => x.User.Identity).Returns(mockIdentity.Object); mockIdentity.Setup(x => x.Name).Returns("test_name");
有关详细信息,请参阅此内容: http : //msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.identityextensions.getuserid(v = vs111).aspx
您不能直接模拟扩展方法,因此最好的方法是向下钻取,直到您点击扩展方法所依赖的可模拟的属性和方法。
在这种情况下, IIdentity.GetuUserId()
是一种扩展方法。 我发布它,但该库目前不是开源的,所以你必须亲自看看GetUserId()
依赖于ClaimsIdentity.FindFirstValue()
。 事实certificate,这也是一种扩展方法,但它依赖于ClaimsIdentity.FindFirst()
,它被标记为virtual
。 现在我们有了接缝,所以我们可以做到以下几点:
var claim = new Claim("test", "IdOfYourChoosing"); var mockIdentity = Mock.Of(ci => ci.FindFirst(It.IsAny()) == claim); var controller = new MyController() { User = Mock.Of(ip => ip.Identity == mockIdentity) }; controller.User.Identity.GetUserId(); //returns "IdOfYourChoosing"
更新:我刚刚意识到我上面发布的解决方案仅适用于派生的ApiControllers
(如Web API)。 MVC Controller
类没有可设置的User
属性。 幸运的是,通过Controller
的ControllerContext
来实现所需的效果非常容易:
var claim = new Claim("test", "IdOfYourChoosing"); var mockIdentity = Mock.Of(ci => ci.FindFirst(It.IsAny()) == claim); var mockContext = Mock.Of(cc => cc.HttpContext.User == mockIdentity); var controller = new MyController() { ControllerContext = mockContext };
但是,如果您要使用User
对象的所有内容都是获取用户的Id,那么另一种方法适用于任何类型的控制器并且需要的代码少得多:
public class MyController: Controller //or ApiController { public Func GetUserId; //For testing public MyController() { GetUserId = () => User.Identity.GetUserId(); } //controller actions }
现在,当您想要用户的Id时,不要调用User.Identity.GetUserId()
,而只需调用GetUserId()
。 当你需要在测试中模拟用户ID时,你只需这样做:
controller = new MyController() { GetUserId = () => "IdOfYourChoosing" };
两种方法都有利弊。 第一种方法更彻底,更灵活,并且使用已经存在于两种控制器类型上的接缝,但它也有更多代码,并且几乎不能读取。 第二种方法更清晰,IMO更具表现力,但它是额外的代码来维护,如果你不使用Func调用来获取用户的Id,你的测试将无法正常工作。 选择哪一个更适合您的情况。
这对我有用
使用fakeiteasy
var identity = new GenericIdentity("TestUsername"); identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "UserIdIWantReturned")); var fakePrincipal = A.Fake(); A.CallTo(() => fakePrincipal.Identity).Returns(identity); var _controller = new MyController { ControllerContext = A.Fake() }; A.CallTo(() => _controller.ControllerContext.HttpContext.User).Returns(fakePrincipal);
现在,您可以从这些IIdentity扩展方法中获取值:
例如。
var userid = _controller.User.Identity.GetUserId(); var userName = _controller.User.Identity.GetUserName();
当用ILSpy查看GetUserId()方法时,它会显示
public static string GetUserId(this IIdentity identity) { if (identity == null) { throw new ArgumentNullException("identity"); } ClaimsIdentity claimsIdentity = identity as ClaimsIdentity; if (claimsIdentity != null) { return claimsIdentity.FindFirstValue(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier); } return null; }
所以GetUserId需要声明“ nameidentifier ”
- 如何在C#/ IL中改变盒装值类型(原语或结构)
- 为什么我的.NET应用程序中出现System.Security.Permissions.SecurityPermission错误?
- entity frameworkMappingException:类型’XXX已被多次映射
- 类库引用问题
- 应该处理sqlexception的策略是什么?
- 如何在静态方法中获取当前类的名称?
- 如何删除/删除数据绑定combobox? SelectedIndex = -1不起作用
- 在edge.js应用程序中加载WCF app.config绑定
- System.BadImageFormatException:无法加载文件或程序集’x_Accessor,…’此程序集由运行时更新程序构建