如何让我的 ServiceStack 测试使用 RestSharp 进行身份验证
本文关键字:RestSharp 身份验证 测试 我的 ServiceStack | 更新日期: 2023-09-27 18:34:30
我在我的ServiceStack应用程序中实现了CustomCredentialsAuth的工作实现。我可以使用身份验证凭据访问 URL,它按预期工作。
然而,在我的测试中,我的运气不一样。
我正在使用 RestSharp,如果我禁用 [Authenticate]
,我可以让我所有的测试通过。
启用[Authenticate]
并运行测试给了我
预期:正常
但是是:未经授权
这是我的测试。如何让 RestSharp 为我的测试进行身份验证?
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 );
}
}
}
我正在使用自定义身份验证提供程序:
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 );
}
}
我的TestAppHostBase像这样连接身份验证。
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() );
}
进一步开发,调用以下代码确实为用户返回 true,但显然不会将会话数据传递给后续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);
因此,事实证明,我们可以想出解决此问题的最佳方法是使用CookieContainer
并将其作为客户端的一部分传递。
首先,我们为 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;
}
}
ServiceInterfaceTests继承自它
[TestFixture]
public class UserServiceInterfaceTests : ServiceInterfaceTestBase
{
然后在我们的设置中,我们调用身份验证方法。
[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);
}
最后,我们的测试看起来像
[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 );
}