Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

417 lines
16 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net.Http.Formatting;
using System.Net.Http.Formatting.Mocks;
using System.Net.Http.Headers;
using System.Threading;
using System.Web.Http;
using System.Web.Http.Hosting;
using System.Web.Http.Routing;
using System.Web.Http.Services;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http
{
public class HttpRequestMessageExtensionsTest
{
private readonly HttpRequestMessage _request = new HttpRequestMessage();
private readonly HttpConfiguration _config = new HttpConfiguration();
private readonly object _value = new object();
private readonly Mock<IDisposable> _disposableMock = new Mock<IDisposable>();
private readonly Mock<IContentNegotiator> _negotiatorMock = new Mock<IContentNegotiator>();
private readonly IDisposable _disposable;
public HttpRequestMessageExtensionsTest()
{
_disposable = _disposableMock.Object;
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = _config;
}
[Fact]
public void GetConfigurationThrowsOnNull()
{
HttpRequestMessage request = null;
Assert.ThrowsArgumentNull(() => request.GetConfiguration(), "request");
}
[Fact]
public void GetConfiguration()
{
// Arrange
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = _config;
// Act
HttpConfiguration afterConfig = _request.GetConfiguration();
// Assert
Assert.Same(_config, afterConfig);
}
[Fact]
public void GetSynchronizationContextThrowsOnNull()
{
HttpRequestMessage request = null;
Assert.ThrowsArgumentNull(() => request.GetSynchronizationContext(), "request");
}
[Fact]
public void GetSynchronizationContext()
{
// Arrange
Mock<SynchronizationContext> syncContextMock = new Mock<SynchronizationContext>();
SynchronizationContext beforeSyncContext = syncContextMock.Object;
_request.Properties.Add(HttpPropertyKeys.SynchronizationContextKey, beforeSyncContext);
// Act
SynchronizationContext afterSyncContext = _request.GetSynchronizationContext();
// Assert
Assert.Same(beforeSyncContext, afterSyncContext);
}
[Fact]
public void GetRouteData()
{
// Arrange
IHttpRouteData routeData = new Mock<IHttpRouteData>().Object;
_request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
// Act
var httpRouteData = _request.GetRouteData();
// Assert
Assert.Same(routeData, httpRouteData);
}
[Fact]
public void GetRouteData_WhenRequestIsNull_Throws()
{
// Arrange
HttpRequestMessage request = null;
// Act
Assert.ThrowsArgumentNull(() => request.GetRouteData(), "request");
}
[Fact]
public void CreateResponse_DoingConneg_OnNullRequest_ThrowsException()
{
HttpRequestMessage request = null;
Assert.ThrowsArgumentNull(() =>
{
request.CreateResponse(HttpStatusCode.OK, _value);
}, "request");
Assert.ThrowsArgumentNull(() =>
{
request.CreateResponse(HttpStatusCode.OK, _value, configuration: null);
}, "request");
}
[Fact]
public void CreateResponse_DoingConneg_OnNullConfiguration_ThrowsException()
{
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = null;
Assert.Throws<InvalidOperationException>(() =>
{
_request.CreateResponse(HttpStatusCode.OK, _value, configuration: null);
}, "The request does not have an associated configuration object or the provided configuration was null.");
}
[Fact]
public void CreateResponse_DoingConneg_RetrievesContentNegotiatorFromServiceResolver()
{
// Arrange
Mock<DefaultServices> servicesMock = new Mock<DefaultServices> { CallBase = true };
servicesMock.Setup(s => s.GetService(typeof(IContentNegotiator)))
.Returns(new Mock<IContentNegotiator>().Object)
.Verifiable();
_config.Services = servicesMock.Object;
// Act
_request.CreateResponse(HttpStatusCode.OK, _value, _config);
// Assert
servicesMock.Verify();
}
[Fact]
public void CreateResponse_DoingConneg_WhenNoContentNegotiatorInstanceRegistered_Throws()
{
// Arrange
_config.Services.Clear(typeof(IContentNegotiator));
// Act & Assert
Assert.Throws<InvalidOperationException>(() => _request.CreateResponse(HttpStatusCode.OK, _value, _config),
"The provided configuration does not have an instance of the 'System.Net.Http.Formatting.IContentNegotiator' service registered.");
}
[Fact]
public void CreateResponse_DoingConneg_WhenContentNegotiatorReturnsNullResult_Throws()
{
// Arrange
_negotiatorMock.Setup(r => r.Negotiate(typeof(string), _request, _config.Formatters)).Returns(value: null);
_config.Services.Replace(typeof(IContentNegotiator), _negotiatorMock.Object);
// Act
var response = _request.CreateResponse<string>(HttpStatusCode.OK, "", _config);
// Assert
Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode);
Assert.Same(_request, response.RequestMessage);
}
[Fact]
public void CreateResponse_DoingConneg_PerformsContentNegotiationAndCreatesContentUsingResults()
{
// Arrange
XmlMediaTypeFormatter formatter = new XmlMediaTypeFormatter();
_negotiatorMock.Setup(r => r.Negotiate(typeof(string), _request, _config.Formatters))
.Returns(new ContentNegotiationResult(formatter, null));
_config.Services.Replace(typeof(IContentNegotiator), _negotiatorMock.Object);
// Act
var response = _request.CreateResponse<string>(HttpStatusCode.NoContent, "42", _config);
// Assert
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
Assert.Same(_request, response.RequestMessage);
var objectContent = Assert.IsType<ObjectContent<string>>(response.Content);
Assert.Equal("42", objectContent.Value);
Assert.Same(formatter, objectContent.Formatter);
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenRequestIsNull_Throws()
{
// Arrange
HttpRequestMessage request = null;
// Act
Assert.ThrowsArgumentNull(() => request.CreateResponse(HttpStatusCode.OK, _value, "foo/bar"), "request");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenMediaTypeHeaderIsNull_Throws()
{
Assert.ThrowsArgumentNull(() => _request.CreateResponse(HttpStatusCode.OK, _value, (MediaTypeHeaderValue)null), "mediaType");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenMediaTypeStringIsNull_Throws()
{
Assert.Throws<ArgumentException>(() => _request.CreateResponse(HttpStatusCode.OK, _value, (string)null), "The value cannot be null or empty.\r\nParameter name: mediaType");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenMediaTypeStringIsEmpty_Throws()
{
Assert.ThrowsArgumentNull(() => _request.CreateResponse(HttpStatusCode.OK, _value, (MediaTypeHeaderValue)null), "mediaType");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenMediaTypeStringIsInvalidFormat_Throws()
{
Assert.Throws<FormatException>(() => _request.CreateResponse(HttpStatusCode.OK, _value, "foo/bar; param=value"), "The format of value 'foo/bar; param=value' is invalid.");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenRequestDoesNotHaveConfiguration_Throws()
{
// Arrange
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = null;
// Act
Assert.Throws<InvalidOperationException>(() => _request.CreateResponse(HttpStatusCode.OK, _value, mediaType: "foo/bar"),
"The request does not have an associated configuration object or the provided configuration was null.");
}
[Fact]
public void CreateResponse_MatchingMediaType_WhenMediaTypeDoesNotMatch_Throws()
{
// Arrange
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration();
// Act
Assert.Throws<InvalidOperationException>(() => _request.CreateResponse(HttpStatusCode.OK, _value, mediaType: "foo/bar"),
"Could not find a formatter matching the media type 'foo/bar' that can write an instance of 'Object'.");
}
[Fact]
public void CreateResponse_MatchingMediaType_FindsMatchingFormatterAndCreatesResponse()
{
// Arrange
var config = new HttpConfiguration();
_request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
config.Formatters.Clear();
Mock<MediaTypeFormatter> formatterMock = new Mock<MediaTypeFormatter> { CallBase = true };
var formatter = formatterMock.Object;
formatterMock.Setup(f => f.CanWriteType(typeof(object))).Returns(true).Verifiable();
formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("foo/bar"));
config.Formatters.Add(formatter);
// Act
var response = _request.CreateResponse(HttpStatusCode.Gone, _value, mediaType: "foo/bar");
// Assert
Assert.Equal(HttpStatusCode.Gone, response.StatusCode);
var content = Assert.IsType<ObjectContent<object>>(response.Content);
Assert.Same(_value, content.Value);
Assert.Same(formatter, content.Formatter);
Assert.Equal("foo/bar", content.Headers.ContentType.MediaType);
formatterMock.Verify();
}
[Fact]
public void CreateResponse_AcceptingFormatter_WhenRequestIsNull_Throws()
{
// Arrange
HttpRequestMessage request = null;
// Act
Assert.ThrowsArgumentNull(() => request.CreateResponse(HttpStatusCode.OK, _value, new MockMediaTypeFormatter()), "request");
}
[Fact]
public void CreateResponse_AcceptingFormatter_WhenFormatterIsNull_Throws()
{
// Act
Assert.ThrowsArgumentNull(() => _request.CreateResponse(HttpStatusCode.OK, _value, formatter: null), "formatter");
}
[Fact]
public void CreateResponse_AcceptingFormatter_CreatesResponseWithDefaultMediaType()
{
// Arrange
var formatter = new MockMediaTypeFormatter { CallBase = true };
formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("foo/bar"));
// Act
var response = _request.CreateResponse(HttpStatusCode.MultipleChoices, _value, formatter, mediaType: (string)null);
// Assert
Assert.Equal(HttpStatusCode.MultipleChoices, response.StatusCode);
var content = Assert.IsType<ObjectContent<object>>(response.Content);
Assert.Same(_value, content.Value);
Assert.Same(formatter, content.Formatter);
Assert.Equal("foo/bar", content.Headers.ContentType.MediaType);
}
[Fact]
public void CreateResponse_AcceptingFormatter_WithOverridenMediaTypeString_CreatesResponse()
{
// Arrange
var formatter = new MockMediaTypeFormatter { CallBase = true };
formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("foo/bar"));
// Act
var response = _request.CreateResponse(HttpStatusCode.MultipleChoices, _value, formatter, mediaType: "bin/baz");
// Assert
Assert.Equal("bin/baz", response.Content.Headers.ContentType.MediaType);
}
[Fact]
public void CreateResponse_AcceptingFormatter_WithOverridenMediaTypeHeader_CreatesResponse()
{
// Arrange
var formatter = new MockMediaTypeFormatter { CallBase = true };
formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("foo/bar"));
// Act
var response = _request.CreateResponse(HttpStatusCode.MultipleChoices, _value, formatter, mediaType: new MediaTypeHeaderValue("bin/baz"));
// Assert
Assert.Equal("bin/baz", response.Content.Headers.ContentType.MediaType);
}
[Fact]
public void RegisterForDispose_WhenRequestParameterIsNull_Throws()
{
HttpRequestMessage request = null;
Assert.ThrowsArgumentNull(() => request.RegisterForDispose(resource: null), "request");
}
[Fact]
public void RegisterForDispose_WhenResourceParamterIsNull_DoesNothing()
{
_request.RegisterForDispose(resource: null);
Assert.False(_request.Properties.ContainsKey(HttpPropertyKeys.DisposableRequestResourcesKey));
}
[Fact]
public void RegisterForDispose_WhenResourceListDoesNotExist_CreatesListAndAddsResource()
{
_request.Properties.Remove(HttpPropertyKeys.DisposableRequestResourcesKey);
_request.RegisterForDispose(_disposable);
var list = Assert.IsType<List<IDisposable>>(_request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey]);
Assert.Equal(1, list.Count);
Assert.Same(_disposable, list[0]);
}
[Fact]
public void RegisterForDispose_WhenResourceListExists_AddsResource()
{
var list = new List<IDisposable>();
_request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey] = list;
_request.RegisterForDispose(_disposable);
Assert.Same(list, _request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey]);
Assert.Equal(1, list.Count);
Assert.Same(_disposable, list[0]);
}
[Fact]
public void DisposeRequestResources_WhenRequestParameterIsNull_Throws()
{
HttpRequestMessage request = null;
Assert.ThrowsArgumentNull(() => request.DisposeRequestResources(), "request");
}
[Fact]
public void DisposeRequestResources_WhenResourceListDoesNotExists_DoesNothing()
{
_request.Properties.Remove(HttpPropertyKeys.DisposableRequestResourcesKey);
_request.DisposeRequestResources();
Assert.False(_request.Properties.ContainsKey(HttpPropertyKeys.DisposableRequestResourcesKey));
}
[Fact]
public void DisposeRequestResources_WhenResourceListExists_DisposesResourceAndClearsReferences()
{
var list = new List<IDisposable> { _disposable };
_request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey] = list;
_request.DisposeRequestResources();
_disposableMock.Verify(d => d.Dispose());
Assert.Empty(list);
}
[Fact]
public void DisposeRequestResources_WhenResourcesDisposeMethodThrowsException_IgnoresExceptionsAndContinuesDisposingOtherResources()
{
Mock<IDisposable> throwingDisposableMock = new Mock<IDisposable>();
throwingDisposableMock.Setup(d => d.Dispose()).Throws(new Exception());
var list = new List<IDisposable> { throwingDisposableMock.Object, _disposable };
_request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey] = list;
_request.DisposeRequestResources();
throwingDisposableMock.Verify(d => d.Dispose());
_disposableMock.Verify(d => d.Dispose());
Assert.Empty(list);
}
}
}