我怎样才能让我的ServiceStack测试使用RestSharp认证? [英] How can I get my ServiceStack Tests to authenticate using RestSharp?

查看:285
本文介绍了我怎样才能让我的ServiceStack测试使用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 me

Expected: OK
But was: Unauthorized

Here 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆