我怎样才能让我的ServiceStack测试使用RestSharp认证? [英] How can I get my ServiceStack Tests to authenticate using RestSharp?
问题描述
我有我的ServiceStack应用实施CustomCredentialsAuth的工作落实。我打与权威性凭据的URL,它按预期工作。
在我的测试中不过,我不是有同样的运气。
我使用RestSharp,如果我禁用 [授权]
,我可以得到我所有的测试通过。
启用 [授权]
和运行测试给我
预计:OK结果
但:未经授权
块引用>下面是我的测试。我怎样才能得到RestSharp为我的测试验证?
使用系统;
使用System.Net;
使用FutureState.AppCore.Tests.Integration.Repositories.Fixtures;
使用NUnit.Framework;
使用RestSharp;命名空间FutureState.AppCore.Tests.Functional.Services
{
[的TestFixture]
公共类UserServiceInterfaceTests
{
私人RestSchemaValidator _restSchemaValidator;
私人字符串_testLoginEmail;
私人字符串_testLoginPassword; [建立]
公共无效设置()
{
_restSchemaValidator =新RestSchemaValidator();
_testLoginEmail = UserFixture.SystemAccount.Email;
_testLoginPassword =密码; } [测试]
公共无效ShouldGetAListOfUsersAndReturnStatusOk()
{
// 建立
VAR的客户=新RESTClient实现(ServiceTestAppHostBase.BaseUrl);
client.Authenticator =新HttpBasicAuthenticator(_testLoginEmail,_testLoginPassword);
VAR要求=新RestRequest(/用户/,Method.GET){RequestFormat = DataFormat.Json}; // 执行
VAR响应= client.Execute(请求); //断言
Assert.That(response.ErrorMessage,Is.Null);
Assert.That(response.Status code,Is.EqualTo(的HTTPStatus code.OK));
_restSchemaValidator.ValidateResponse(ExpectedUsersResponse.json,response.Content);
} [测试]
公共无效ShouldGetAUserAndReturnStatusOk()
{
// 建立
VAR expectedUserId =新的GUID(UserFixture.FirstUserId);
VAR的客户=新RESTClient实现(ServiceTestAppHostBase.BaseUrl);
client.Authenticator =新HttpBasicAuthenticator(_testLoginEmail,_testLoginPassword);
VAR要求=新RestRequest(/用户/+ expectedUserId,Method.GET){RequestFormat = DataFormat.Json}; // 执行
VAR响应= client.Execute(请求); //断言
Assert.That(response.ErrorMessage,Is.Null);
Assert.That(response.Status code,Is.EqualTo(的HTTPStatus code.OK));
_restSchemaValidator.ValidateResponse(ExpectedUserResponse.json,response.Content);
}
}
}我使用的是自定义的身份验证提供者:
公共类CustomCredentialsAuthProvider:CredentialsAuthProvider
{
私人只读IUserService _userService;
私人的Guid _userId; 公共CustomCredentialsAuthProvider(集装箱货柜)
{
_userService = container.Resolve< IUserService>();
} 公众覆盖布尔TryAuthenticate(IServiceBase authService,字符串email,字符串密码)
{
变种用户= _userService.GetByEmailAddress(电子邮件);
user.password的=密码; //验证之前张贴的密码用户对象添加。 _userId = user.Id;
返回_userService.CheckPassword(用户);
} OnAuthenticated公共覆盖无效(IServiceBase authService,IAuthSession会议,IOAuthTokens令牌,字典<字符串,字符串> AUTHINFO)
{
session.Id = _userId.ToString(); //重要提示:您需要保存会话!
authService.SaveSession(会话,SessionExpiry);
}
}和我TestAppHostBase线了AUTH这个样子。
私人无效ConfigureAuth(集装箱货柜)
{ //默认路由:/认证/ {}提供商
Plugins.Add(新AuthFeature(()=>新建AuthUserSession()
新IAuthProvider [] {
新CustomCredentialsAuthProvider(集装箱)
})); //默认路由:/寄存器
Plugins.Add(新RegistrationFeature());}进一步发展,调用下面code的 DOES 的为用户返回true,但显然不会话数据传递给后续的
RestRequest
。//调用此为TryAuthenticate返回TRUE
//但不保留的subsequenet请求的会话数据。
VAR容器= EndpointHost.AppHost.TryResolve<集装箱>();
VAR authService =新AuthService();
VAR customCredentialsAuthProvider =新CustomCredentialsAuthProvider(容器);
customCredentialsAuthProvider.TryAuthenticate(authService,_testLoginEmail,_testLoginPassword);
解决方案因此,原来最好的办法,我们可以拿出来解决这个问题是使用
的CookieContainer
并把它作为所述客户机的一个组成部分。首先,我们做了一个基类为我们ServiceInterfaceTests
公共类ServiceInterfaceTestBase
{
保护IRestClient客户端;
保护无效AuthenticateClient(字符串email,字符串密码)
{ 客户端=新RESTClient实现(ServiceTestAppHostBase.BaseUrl);
VAR登录=新RestRequest(/ AUTH,Method.POST);
login.AddParameter(用户名,邮件);
login.AddParameter(密码,密码); VAR响应= Client.Execute(登录);
VAR cookieJar =新的CookieContainer(); 如果(response.Status code ==的HTTPStatus code.OK)
{
变种的Cookie = response.Cookies.FirstOrDefault();
cookieJar.Add(新的Cookie(cookie.Name,cookie.Value,cookie.Path,cookie.Domain));
} Client.CookieContainer = cookieJar;
}
}该ServiceInterfaceTests从它继承
[的TestFixture]
公共类UserServiceInterfaceTests:ServiceInterfaceTestBase
{然后在我们的设置,我们称之为AUTH方法。
[设置]
公共无效设置()
{
_restSchemaValidator =新RestSchemaValidator();
_testLoginEmail = UserFixture.SystemAccount.Email;
_testLoginPassword =密码; //数据库包含密码的哈希密码的版本。 AuthenticateClient(_testLoginEmail,_testLoginPassword);
}和最后我们的测试看起来像
[测试]
公共无效ShouldGetAListOfUsersAndReturnStatusOk()
{
// 建立
VAR要求=新RestRequest(/用户/,Method.GET){RequestFormat = DataFormat.Json,}; // 执行
VAR响应= Client.Execute(请求); //断言
Assert.That(response.ErrorMessage,Is.Null);
Assert.That(response.Status code,Is.EqualTo(的HTTPStatus code.OK));
_restSchemaValidator.ValidateResponse(ExpectedUsersResponse.json,response.Content);
Trace.Write(response.Content);
}I've got a working implementation of CustomCredentialsAuth implemented in my ServiceStack app. I can hit the URL with auth credentials, and it works as expected.
In my tests however, I'm not having the same luck.
I'm using RestSharp, and if I disable
[Authenticate]
, I can get all of my tests to pass.Enabling
[Authenticate]
and running the tests give meExpected: OK
But was: UnauthorizedHere is my test. How can I get RestSharp to authenticate for my tests?
using System; using System.Net; using FutureState.AppCore.Tests.Integration.Repositories.Fixtures; using NUnit.Framework; using RestSharp; namespace FutureState.AppCore.Tests.Functional.Services { [TestFixture] public class UserServiceInterfaceTests { private RestSchemaValidator _restSchemaValidator; private string _testLoginEmail; private string _testLoginPassword; [SetUp] public void SetUp () { _restSchemaValidator = new RestSchemaValidator(); _testLoginEmail = UserFixture.SystemAccount.Email; _testLoginPassword = "password"; } [Test] public void ShouldGetAListOfUsersAndReturnStatusOk () { // Setup var client = new RestClient( ServiceTestAppHostBase.BaseUrl ); client.Authenticator = new HttpBasicAuthenticator( _testLoginEmail, _testLoginPassword ); var request = new RestRequest( "/users/", Method.GET ) { RequestFormat = DataFormat.Json }; // Execute var response = client.Execute( request ); // Assert Assert.That( response.ErrorMessage, Is.Null ); Assert.That( response.StatusCode, Is.EqualTo( HttpStatusCode.OK ) ); _restSchemaValidator.ValidateResponse( "ExpectedUsersResponse.json", response.Content ); } [Test] public void ShouldGetAUserAndReturnStatusOk () { // Setup var expectedUserId = new Guid( UserFixture.FirstUserId ); var client = new RestClient( ServiceTestAppHostBase.BaseUrl ); client.Authenticator = new HttpBasicAuthenticator( _testLoginEmail, _testLoginPassword ); var request = new RestRequest( "/users/" + expectedUserId, Method.GET ) { RequestFormat = DataFormat.Json }; // Execute var response = client.Execute( request ); // Assert Assert.That( response.ErrorMessage, Is.Null ); Assert.That( response.StatusCode, Is.EqualTo( HttpStatusCode.OK ) ); _restSchemaValidator.ValidateResponse( "ExpectedUserResponse.json", response.Content ); } } }
I'm using a custom auth provider:
public class CustomCredentialsAuthProvider : CredentialsAuthProvider { private readonly IUserService _userService; private Guid _userId; public CustomCredentialsAuthProvider ( Container container ) { _userService = container.Resolve<IUserService>(); } public override bool TryAuthenticate ( IServiceBase authService, string email, string password ) { var user = _userService.GetByEmailAddress( email ); user.Password = password; // Add the posted password to the user object before authenticating. _userId = user.Id; return _userService.CheckPassword( user ); } public override void OnAuthenticated ( IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo ) { session.Id = _userId.ToString(); //Important: You need to save the session! authService.SaveSession( session, SessionExpiry ); } }
And my TestAppHostBase wires up the auth like this.
private void ConfigureAuth ( Container container ) { //Default route: /auth/{provider} Plugins.Add( new AuthFeature( () => new AuthUserSession(), new IAuthProvider[] { new CustomCredentialsAuthProvider(container) } ) ); //Default route: /register Plugins.Add( new RegistrationFeature() ); }
Further development, calling the following code DOES return true for the user, but obviously doesn't pass the session data to the subsequent
RestRequest
.// Calling this returns TRUE for TryAuthenticate // But doesn't retain the session data for the subsequenet request. var container = EndpointHost.AppHost.TryResolve<Container>(); var authService = new AuthService(); var customCredentialsAuthProvider = new CustomCredentialsAuthProvider( container ); customCredentialsAuthProvider.TryAuthenticate(authService, _testLoginEmail, _testLoginPassword);
解决方案So it turns out the best way we could come up with to solve this is to use a
CookieContainer
and pass it as a part of the client.First we made a base class for our ServiceInterfaceTests
public class ServiceInterfaceTestBase { protected IRestClient Client; protected void AuthenticateClient(string email, string password) { Client = new RestClient( ServiceTestAppHostBase.BaseUrl ); var login = new RestRequest( "/auth", Method.POST ); login.AddParameter( "username", email ); login.AddParameter( "password", password ); var response = Client.Execute( login ); var cookieJar = new CookieContainer(); if ( response.StatusCode == HttpStatusCode.OK ) { var cookie = response.Cookies.FirstOrDefault(); cookieJar.Add( new Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain ) ); } Client.CookieContainer = cookieJar; } }
The ServiceInterfaceTests inherit from it
[TestFixture] public class UserServiceInterfaceTests : ServiceInterfaceTestBase {
Then in our Setup, we call the auth method.
[SetUp] public void SetUp () { _restSchemaValidator = new RestSchemaValidator(); _testLoginEmail = UserFixture.SystemAccount.Email; _testLoginPassword = "password"; // the database contains a hashed password version of "password". AuthenticateClient(_testLoginEmail, _testLoginPassword); }
And lastly our Test will look like
[Test] public void ShouldGetAListOfUsersAndReturnStatusOk () { // Setup var request = new RestRequest( "/users/", Method.GET ) { RequestFormat = DataFormat.Json, }; // Execute var response = Client.Execute( request ); // Assert Assert.That( response.ErrorMessage, Is.Null ); Assert.That( response.StatusCode, Is.EqualTo( HttpStatusCode.OK ) ); _restSchemaValidator.ValidateResponse( "ExpectedUsersResponse.json", response.Content ); Trace.Write( response.Content ); }
这篇关于我怎样才能让我的ServiceStack测试使用RestSharp认证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!