如何使用RestSharp进行ServiceStack测试以进行身份​​验证?

时间:2013-10-08 17:32:39

标签: c# authentication testing servicestack restsharp

我在ServiceStack应用程序中实现了CustomCredentialsAuth的工作实现。我可以使用auth凭据来访问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就像这样连接了auth。

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() );

}

进一步开发,调用以下代码 DOES 为用户返回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);

1 个答案:

答案 0 :(得分:2)

因此,事实证明,解决此问题的最佳方法是使用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
{

然后在我们的设置中,我们调用auth方法。

[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 );
}