Bar*_*cer 5 c# integration-testing web-config authorize-attribute asp.net-web-api
所以我发现在[Authorize]标签上有些东西让我有所启发,但没有什么可以解决我的问题.
我的场景是我有Web Api方法,我希望使用RestSharp进行集成测试.但是RestSharp正在获取我的登录页面,而不是调用的结果.
[Authorize]
public Item GetItem([FromBody] int id)
{
return service.GetItem(id);
}
Run Code Online (Sandbox Code Playgroud)
该产品使用自定义登录系统,我真正想要的是一种只为集成测试禁用[授权]徽章的方法.但是我读到你可以允许匿名用户,它会"禁用"徽章,所以在解决方案中,我有一个集成测试项目,在那个项目中我有一个App.config文件.在那个文件中,我把:
<location>
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
Run Code Online (Sandbox Code Playgroud)
但这似乎也不起作用.任何有关正在发生的事情的解释,为什么它不起作用以及如何才能使这项工作将不胜感激.
我试图设置一个Thread.CurrentPrincipal,但是没有用(也许我做错了 - 你能在代码中设置"任何东西"吗?).如果有帮助,则在httpmodule中处理身份验证.
我意识到这个问题是关于在webapi端点触发RestSharp的"真实"请求,所以这个建议不能立即适用于OP场景.但是:
我正在使用内存中的Web Api测试HttpConfiguration,HttpServer并且HttpMessageInvoker(很像Badri的建议,我相信).通过这种方式,我不需要监听器或端口打开,因为我可以在内存中测试完整的堆栈(端到端测试) - 在构建服务器,Heroku实例等上非常方便.
使用内存中的测试,这里是你如何设置Thread.CurrentPrincipal..我有一个帮助我的测试基类,如下所示:
protected void AuthentateRequest()
{
Thread.CurrentPrincipal = new AuthenticatedPrincipal(Thread.CurrentPrincipal);
}
Run Code Online (Sandbox Code Playgroud)
哪个使用这个:
public class AuthenticatedPrincipal : IPrincipal
{
private readonly IPrincipal _principalToWrap;
private readonly IIdentity _identityToWrap;
public AuthenticatedPrincipal(IPrincipal principalToWrap)
{
_principalToWrap = principalToWrap;
_identityToWrap = new AuthenticatedIdentity(principalToWrap.Identity);
}
public bool IsInRole(string role)
{ return _principalToWrap.IsInRole(role); }
public IIdentity Identity
{
get { return _identityToWrap; }
private set { throw new NotSupportedException(); }
}
}
public class AuthenticatedIdentity : IIdentity
{
private readonly IIdentity _identityToWrap;
public AuthenticatedIdentity(IIdentity identityToWrap)
{
_identityToWrap = identityToWrap;
}
public string Name
{
get { return _identityToWrap.Name; }
private set { throw new NotSupportedException(); }
}
public string AuthenticationType
{
get { return _identityToWrap.AuthenticationType; }
private set { throw new NotSupportedException(); }
}
public bool IsAuthenticated
{
get { return true; }
private set { throw new NotSupportedException(); }
}
}
Run Code Online (Sandbox Code Playgroud)
IPrincipal手动存根可能看起来有点过分,但是我尝试使用我的模拟框架,它在我的一些测试运行器(Resharper和TeamCity,但不是NCrunch - 我认为在AppDomains上进行序列化的事情)中爆炸了.
这将设置Thread.CurrentPrincipal在ApiControlleraction方法内部,因此愚弄AuthorizeAttribute相信你是经过身份验证的.
这是你应该如何设置的Thread.CurrentPrincipal.将这样的消息处理程序添加到Web API项目中,并在类似的Register方法中添加处理程序WebApiConfig.cs:config.MessageHandlers.Add(new MyTestHandler());.
public class MyTestHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var local = request.Properties["MS_IsLocal"] as Lazy<bool>;
bool isLocal = local != null && local.Value;
if (isLocal)
{
if (request.Headers.GetValues("X-Testing").First().Equals("true"))
{
var dummyPrincipal = new GenericPrincipal(
new GenericIdentity("dummy", "dummy"),
new[] { "myrole1" });
Thread.CurrentPrincipal = dummyPrincipal;
if (HttpContext.Current != null)
HttpContext.Current.User = dummyPrincipal;
}
}
return await base.SendAsync(request, cancellationToken);
}
}
Run Code Online (Sandbox Code Playgroud)
此处理程序设置经过身份验证的主体,以使您[Authorize]满意.这种方法存在风险因素.仅用于测试,您应该将此处理程序插入Web API管道.如果将此处理程序插入生产代码中的管道(有意或无意),它基本上会破坏您的身份验证机制.为了在某种程度上降低风险(希望API不在本地访问),我检查以确保访问是本地的,并且有X-Testing一个值为的标头true.
从RestSharp中,添加自定义标头.
var request = new RestRequest(...);
request.AddHeader("X-Testing", "true");
Run Code Online (Sandbox Code Playgroud)
顺便说一下,对于集成测试,我宁愿使用内存托管,而不是网络托管.这样,Web API就可以在同一个测试项目中运行,您可以随心所欲地使用它,而不必担心会破坏生产中的某些内容.有关内存的主机的详细信息,请参阅该和这个.
| 归档时间: |
|
| 查看次数: |
3767 次 |
| 最近记录: |