#229 HttpTest.Settings should always take precedence

This commit is contained in:
Todd Menier 2017-10-03 16:43:10 -05:00
parent 014e5c20fd
commit 22ab91b43a
6 changed files with 74 additions and 24 deletions

View File

@ -261,6 +261,35 @@ namespace Flurl.Test.Http
await Task.WhenAll(tasks); // failed HTTP status, etc, would throw here and fail the test. await Task.WhenAll(tasks); // failed HTTP status, etc, would throw here and fail the test.
} }
[Test]
public async Task test_settings_override_client_settings() {
var cli1 = new FlurlClient();
cli1.Settings.HttpClientFactory = new DefaultHttpClientFactory();
var h = cli1.HttpClient; // force (lazy) instantiation
using (var test = new HttpTest()) {
test.Settings.CookiesEnabled = false;
test.RespondWith("foo!");
var s = await cli1.Request("http://www.google.com")
.EnableCookies() // test says cookies are off, and test should always win
.GetStringAsync();
Assert.AreEqual("foo!", s);
Assert.IsFalse(cli1.Settings.CookiesEnabled);
var cli2 = new FlurlClient();
cli2.Settings.HttpClientFactory = new DefaultHttpClientFactory();
h = cli2.HttpClient;
test.RespondWith("foo 2!");
s = await cli2.Request("http://www.google.com")
.EnableCookies() // test says cookies are off, and test should always win
.GetStringAsync();
Assert.AreEqual("foo 2!", s);
Assert.IsFalse(cli2.Settings.CookiesEnabled);
}
}
public class DelegatingHandlerHttpClientFactory : DefaultHttpClientFactory public class DelegatingHandlerHttpClientFactory : DefaultHttpClientFactory
{ {
public override HttpMessageHandler CreateMessageHandler() { public override HttpMessageHandler CreateMessageHandler() {

View File

@ -179,7 +179,7 @@ namespace Flurl.Test.Http
var rec = "http://www.api.com".EnableCookies(); var rec = "http://www.api.com".EnableCookies();
await rec.GetAsync(); await rec.GetAsync();
Assert.AreEqual(1, rec.Cookies.Count()); Assert.AreEqual(1, rec.Cookies.Count);
Assert.AreEqual("foo", rec.Cookies["c1"].Value); Assert.AreEqual("foo", rec.Cookies["c1"].Value);
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Flurl.Http.Testing;
namespace Flurl.Http.Configuration namespace Flurl.Http.Configuration
{ {
@ -137,7 +138,9 @@ namespace Flurl.Http.Configuration
/// </summary> /// </summary>
protected T Get<T>(Expression<Func<T>> property) { protected T Get<T>(Expression<Func<T>> property) {
var p = (property.Body as MemberExpression).Member as PropertyInfo; var p = (property.Body as MemberExpression).Member as PropertyInfo;
var testVals = HttpTest.Current?.Settings._vals;
return return
testVals?.ContainsKey(p.Name) == true ? (T)testVals[p.Name] :
_vals.ContainsKey(p.Name) ? (T)_vals[p.Name] : _vals.ContainsKey(p.Name) ? (T)_vals[p.Name] :
_defaults != null ? (T)p.GetValue(_defaults) : _defaults != null ? (T)p.GetValue(_defaults) :
default(T); default(T);
@ -206,7 +209,10 @@ namespace Flurl.Http.Configuration
/// Gets or sets the factory that defines creating, caching, and reusing FlurlClient instances and, /// Gets or sets the factory that defines creating, caching, and reusing FlurlClient instances and,
/// by proxy, HttpClient instances. /// by proxy, HttpClient instances.
/// </summary> /// </summary>
public IFlurlClientFactory FlurlClientFactory { get; set; } public IFlurlClientFactory FlurlClientFactory {
get => Get(() => FlurlClientFactory);
set => Set(() => FlurlClientFactory, value);
}
/// <summary> /// <summary>
/// Resets all global settings to their Flurl.Http-defined default values. /// Resets all global settings to their Flurl.Http-defined default values.
@ -214,11 +220,25 @@ namespace Flurl.Http.Configuration
public override void ResetDefaults() { public override void ResetDefaults() {
base.ResetDefaults(); base.ResetDefaults();
Timeout = TimeSpan.FromSeconds(100); // same as HttpClient Timeout = TimeSpan.FromSeconds(100); // same as HttpClient
CookiesEnabled = false;
JsonSerializer = new NewtonsoftJsonSerializer(null); JsonSerializer = new NewtonsoftJsonSerializer(null);
UrlEncodedSerializer = new DefaultUrlEncodedSerializer(); UrlEncodedSerializer = new DefaultUrlEncodedSerializer();
FlurlClientFactory = new PerHostFlurlClientFactory(); FlurlClientFactory = new PerHostFlurlClientFactory();
HttpClientFactory = new DefaultHttpClientFactory(); HttpClientFactory = new DefaultHttpClientFactory();
} }
} }
/// <summary>
/// Settings overrides within the context of an HttpTest
/// </summary>
public class TestFlurlHttpSettings : GlobalFlurlHttpSettings
{
/// <summary>
/// Resets all test settings to their Flurl.Http-defined default values.
/// </summary>
public override void ResetDefaults() {
base.ResetDefaults();
FlurlClientFactory = new TestFlurlClientFactory();
HttpClientFactory = new TestHttpClientFactory();
}
}
} }

View File

@ -4,6 +4,7 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Linq; using System.Linq;
using Flurl.Http.Configuration; using Flurl.Http.Configuration;
using Flurl.Http.Testing;
using Flurl.Util; using Flurl.Util;
namespace Flurl.Http namespace Flurl.Http
@ -69,10 +70,7 @@ namespace Flurl.Http
BaseUrl = baseUrl; BaseUrl = baseUrl;
Settings = new ClientFlurlHttpSettings(FlurlHttp.GlobalSettings); Settings = new ClientFlurlHttpSettings(FlurlHttp.GlobalSettings);
_httpClient = new Lazy<HttpClient>(() => Settings.HttpClientFactory.CreateHttpClient(HttpMessageHandler)); _httpClient = new Lazy<HttpClient>(() => Settings.HttpClientFactory.CreateHttpClient(HttpMessageHandler));
_httpMessageHandler = new Lazy<HttpMessageHandler>(() => { _httpMessageHandler = new Lazy<HttpMessageHandler>(() => Settings.HttpClientFactory.CreateMessageHandler());
_connectionLeaseStart = DateTime.UtcNow;
return Settings.HttpClientFactory.CreateMessageHandler();
});
} }
/// <inheritdoc /> /// <inheritdoc />
@ -88,10 +86,10 @@ namespace Flurl.Http
public IDictionary<string, Cookie> Cookies { get; } = new Dictionary<string, Cookie>(); public IDictionary<string, Cookie> Cookies { get; } = new Dictionary<string, Cookie>();
/// <inheritdoc /> /// <inheritdoc />
public HttpClient HttpClient => _httpClient.Value; public HttpClient HttpClient => HttpTest.Current?.HttpClient ?? _httpClient.Value;
/// <inheritdoc /> /// <inheritdoc />
public HttpMessageHandler HttpMessageHandler => _httpMessageHandler.Value; public HttpMessageHandler HttpMessageHandler => HttpTest.Current?.HttpMessageHandler ?? _httpMessageHandler.Value;
/// <inheritdoc /> /// <inheritdoc />
public IFlurlRequest Request(params object[] urlSegments) { public IFlurlRequest Request(params object[] urlSegments) {
@ -112,13 +110,12 @@ namespace Flurl.Http
set => Settings = value as ClientFlurlHttpSettings; set => Settings = value as ClientFlurlHttpSettings;
} }
private DateTime? _connectionLeaseStart = null; private Lazy<DateTime> _connectionLeaseStart = new Lazy<DateTime>(() => DateTime.UtcNow);
private readonly object _connectionLeaseLock = new object(); private readonly object _connectionLeaseLock = new object();
private bool IsConnectionLeaseExpired => private bool IsConnectionLeaseExpired =>
_connectionLeaseStart.HasValue &&
Settings.ConnectionLeaseTimeout.HasValue && Settings.ConnectionLeaseTimeout.HasValue &&
DateTime.UtcNow - _connectionLeaseStart > Settings.ConnectionLeaseTimeout; DateTime.UtcNow - _connectionLeaseStart.Value > Settings.ConnectionLeaseTimeout;
/// <inheritdoc /> /// <inheritdoc />
public bool CheckAndRenewConnectionLease() { public bool CheckAndRenewConnectionLease() {
@ -126,7 +123,7 @@ namespace Flurl.Http
if (IsConnectionLeaseExpired) { if (IsConnectionLeaseExpired) {
lock (_connectionLeaseLock) { lock (_connectionLeaseLock) {
if (IsConnectionLeaseExpired) { if (IsConnectionLeaseExpired) {
_connectionLeaseStart = DateTime.UtcNow; _connectionLeaseStart = new Lazy<DateTime>(() => DateTime.UtcNow);
return true; return true;
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using Flurl.Http.Configuration; using Flurl.Http.Configuration;
using Flurl.Http.Testing;
namespace Flurl.Http namespace Flurl.Http
{ {
@ -17,7 +16,7 @@ namespace Flurl.Http
/// <summary> /// <summary>
/// Globally configured Flurl.Http settings. Should normally be written to by calling FlurlHttp.Configure once application at startup. /// Globally configured Flurl.Http settings. Should normally be written to by calling FlurlHttp.Configure once application at startup.
/// </summary> /// </summary>
public static GlobalFlurlHttpSettings GlobalSettings => HttpTest.Current?.Settings ?? _settings.Value; public static GlobalFlurlHttpSettings GlobalSettings => _settings.Value;
/// <summary> /// <summary>
/// Provides thread-safe access to Flurl.Http's global configuration settings. Should only be called once at application startup. /// Provides thread-safe access to Flurl.Http's global configuration settings. Should only be called once at application startup.

View File

@ -15,20 +15,25 @@ namespace Flurl.Http.Testing
/// </summary> /// </summary>
public class HttpTest : IDisposable public class HttpTest : IDisposable
{ {
private readonly Lazy<HttpClient> _httpClient;
private readonly Lazy<HttpMessageHandler> _httpMessageHandler;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HttpTest"/> class. /// Initializes a new instance of the <see cref="HttpTest"/> class.
/// </summary> /// </summary>
/// <exception cref="Exception">A delegate callback throws an exception.</exception> /// <exception cref="Exception">A delegate callback throws an exception.</exception>
public HttpTest() { public HttpTest() {
Settings = new GlobalFlurlHttpSettings { Settings = new TestFlurlHttpSettings();
HttpClientFactory = new TestHttpClientFactory(),
FlurlClientFactory = new TestFlurlClientFactory()
};
ResponseQueue = new Queue<HttpResponseMessage>(); ResponseQueue = new Queue<HttpResponseMessage>();
CallLog = new List<HttpCall>(); CallLog = new List<HttpCall>();
_httpClient = new Lazy<HttpClient>(() => Settings.HttpClientFactory.CreateHttpClient(HttpMessageHandler));
_httpMessageHandler = new Lazy<HttpMessageHandler>(() => Settings.HttpClientFactory.CreateMessageHandler());
SetCurrentTest(this); SetCurrentTest(this);
} }
internal HttpClient HttpClient => _httpClient.Value;
internal HttpMessageHandler HttpMessageHandler => _httpMessageHandler.Value;
/// <summary> /// <summary>
/// Gets or sets the FlurlHttpSettings object used by this test. /// Gets or sets the FlurlHttpSettings object used by this test.
/// </summary> /// </summary>