Skip to content

Commit

Permalink
Implemented a rest client that can serialize payloads using an ISeria…
Browse files Browse the repository at this point in the history
…lizer before sending the request to the HTTP client. Then turn around and deserialize the content using ISerializer to a type we provide from the response.
  • Loading branch information
dragan committed Aug 28, 2010
1 parent 26259bd commit cdf8c9d
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 9 deletions.
16 changes: 8 additions & 8 deletions src/SineSignal.Ottoman.Specs/CouchProxySpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ public void Should_return_deserialized_object()
Assert.That(resultStub.Status, Is.EqualTo("completed"));
}
}

public class ResultStub
{
public string Status { get; private set; }
}

public class ResultStub
{
public string Status { get; private set; }

public ResultStub()
{
Status = "completed";
}
public ResultStub()
{
Status = "completed";
}
}
}
106 changes: 106 additions & 0 deletions src/SineSignal.Ottoman.Specs/Http/RestClientSpecs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System;
using System.Net;

using NSubstitute;
using NUnit.Framework;
using SineSignal.Ottoman.Specs.Framework;

using SineSignal.Ottoman.Http;
using SineSignal.Ottoman.Serialization;

namespace SineSignal.Ottoman.Specs.Http
{
public class RestClientSpecs
{
public class When_processing_a_post_request : ConcernFor<RestClient>
{
private Uri baseUri;
private IHttpClient httpClient;
private RestRequest restRequest;
private Employee payload;
private RestResponse<ResultStub> restResponse;
private ISerializer serializer;
private string requestContent;
private string responseContent;
private ResultStub contentDeserialized;
private string jsonContentType;

protected override void Given()
{
baseUri = new Uri("http://127.0.0.1:5984");
payload = new Employee { Name = "Bob", Login = "boblogin" };
restRequest = new RestRequest { Path = "some/path", Method = HttpMethod.Post, Payload = payload };
requestContent = "{\"Id\":\"" + Guid.Empty + "\",\"Name\":\"\",\"Login\":\"\"}";
responseContent = "{\"status\":\"completed\"}";
jsonContentType = "application/json";

serializer = Fake<ISerializer>();
serializer.Serialize(Arg.Any<object>()).Returns(requestContent);
contentDeserialized = new ResultStub();
serializer.Deserialize<ResultStub>(Arg.Any<string>()).Returns(contentDeserialized);

httpClient = Fake<IHttpClient>();
httpClient.Send(Arg.Any<HttpRequest>()).Returns(new HttpResponse {
ContentType = jsonContentType,
ContentLength = responseContent.Length,
Content = responseContent,
StatusCode = HttpStatusCode.Created,
StatusDescription = HttpStatusCode.Created.ToString()
});
}

public override RestClient CreateSystemUnderTest()
{
return new RestClient(baseUri, httpClient, serializer);
}

protected override void When()
{
restResponse = Sut.Process<ResultStub>(restRequest);
}

[Test]
public void Should_call_serialize_on_serializer_with_the_payload()
{
serializer.Received().Serialize(Arg.Is<Employee>(e => {
return e.Id == Guid.Empty &&
e.Name == "Bob" &&
e.Login == "boblogin";
}));
}

[Test]
public void Should_call_send_on_http_client_with_generated_http_request()
{
httpClient.Received().Send(Arg.Is<HttpRequest>(h => {
return h.Url == new Uri(baseUri.ToString() + restRequest.Path) &&
h.Accept == jsonContentType &&
h.Method == restRequest.Method &&
h.ContentType == jsonContentType &&
h.Content == requestContent &&
h.ContentLength == requestContent.Length;
}));
}

[Test]
public void Should_call_deserialize_on_serializer_with_content_of_response()
{
serializer.Received().Deserialize<ResultStub>(Arg.Is<string>(s => {
return s == responseContent;
}));
}

[Test]
public void Should_return_rest_response_generated_from_http_response()
{
Assert.That(restResponse.RestRequest, Is.EqualTo(restRequest));
Assert.That(restResponse.ContentType, Is.EqualTo(jsonContentType));
Assert.That(restResponse.Content, Is.EqualTo(responseContent));
Assert.That(restResponse.ContentLength, Is.EqualTo(responseContent.Length));
Assert.That(restResponse.StatusCode, Is.EqualTo(HttpStatusCode.Created));
Assert.That(restResponse.StatusDescription, Is.EqualTo(HttpStatusCode.Created.ToString()));
Assert.That(restResponse.ContentDeserialized, Is.EqualTo(contentDeserialized));
}
}
}
}
2 changes: 2 additions & 0 deletions src/SineSignal.Ottoman.Specs/SineSignal.Ottoman.Specs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<Compile Include="CouchDocumentSessionSpecs.cs" />
<Compile Include="CouchProxySpecs.cs" />
<Compile Include="CouchDocumentSpecs.cs" />
<Compile Include="Http\RestClientSpecs.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SineSignal.Ottoman\SineSignal.Ottoman.csproj">
Expand All @@ -61,5 +62,6 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Folder Include="Framework\" />
<Folder Include="Http\" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/SineSignal.Ottoman/Http/HttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public HttpResponse Send(HttpRequest httpRequest)
private static HttpWebRequest InitializeHttpWebRequest(HttpRequest httpRequest)
{
HttpWebRequest httpWebRequest = WebRequest.Create(httpRequest.Url) as HttpWebRequest;
httpWebRequest.Accept = httpRequest.Accept;
httpWebRequest.UserAgent = USER_AGENT;
httpWebRequest.Method = httpRequest.Method;
httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None;
Expand Down
1 change: 1 addition & 0 deletions src/SineSignal.Ottoman/Http/HttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public sealed class HttpRequest
{
public Uri Url { get; set; }
public IList<HttpHeader> Headers { get; private set; }
public string Accept { get; set; }
public string Method { get; set; }
public string ContentType { get; set; }
public string Content { get; set; }
Expand Down
57 changes: 57 additions & 0 deletions src/SineSignal.Ottoman/Http/RestClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;

using SineSignal.Ottoman.Serialization;

namespace SineSignal.Ottoman.Http
{
public class RestClient : IRestClient
{
private UriBuilder _requestUri;

public Uri BaseUri { get; private set; }
private IHttpClient HttpClient { get; set; }
private ISerializer Serializer { get; set; }

public RestClient(Uri baseUri, IHttpClient httpClient, ISerializer serializer)
{
_requestUri = new UriBuilder(baseUri);
BaseUri = baseUri;
HttpClient = httpClient;
Serializer = serializer;
}

public RestResponse<T> Process<T>(RestRequest restRequest)
{
HttpRequest httpRequest = ConverToHttpRequestFrom(restRequest);
HttpResponse httpResponse = HttpClient.Send(httpRequest);

return ConvertToRestResponseFrom<T>(httpResponse, restRequest);
}

private HttpRequest ConverToHttpRequestFrom(RestRequest restRequest)
{
_requestUri.Path = restRequest.Path;

return new HttpRequest {
Url = _requestUri.Uri,
Accept = "application/json",
Method = restRequest.Method,
ContentType = "application/json",
Content = Serializer.Serialize(restRequest.Payload)
};
}

private RestResponse<T> ConvertToRestResponseFrom<T>(HttpResponse httpResponse, RestRequest restRequest)
{
return new RestResponse<T> {
RestRequest = restRequest,
ContentType = httpResponse.ContentType,
ContentLength = httpResponse.ContentLength,
Content = httpResponse.Content,
StatusCode = httpResponse.StatusCode,
StatusDescription = httpResponse.StatusDescription,
ContentDeserialized = Serializer.Deserialize<T>(httpResponse.Content)
};
}
}
}
4 changes: 3 additions & 1 deletion src/SineSignal.Ottoman/Http/RestResponse.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Net;

namespace SineSignal.Ottoman.Http
{
public class RestResponse<T>
Expand All @@ -6,7 +8,7 @@ public class RestResponse<T>
public string ContentType { get; set; }
public long ContentLength { get; set; }
public string Content { get; set; }
public System.Net.HttpStatusCode StatusCode { get; set; }
public HttpStatusCode StatusCode { get; set; }
public string StatusDescription { get; set; }
public T ContentDeserialized { get; set; }
}
Expand Down
8 changes: 8 additions & 0 deletions src/SineSignal.Ottoman/Serialization/ISerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace SineSignal.Ottoman.Serialization
{
public interface ISerializer
{
string Serialize(object objectToSerialize);
T Deserialize<T>(string content);
}
}
3 changes: 3 additions & 0 deletions src/SineSignal.Ottoman/SineSignal.Ottoman.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
<Compile Include="Http\RestResponse.cs" />
<Compile Include="Http\IRestClient.cs" />
<Compile Include="CouchProxy.cs" />
<Compile Include="Http\RestClient.cs" />
<Compile Include="Serialization\ISerializer.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
Expand All @@ -61,5 +63,6 @@
<Folder Include="Exceptions\" />
<Folder Include="Http\" />
<Folder Include="Commands\" />
<Folder Include="Serialization\" />
</ItemGroup>
</Project>

0 comments on commit cdf8c9d

Please sign in to comment.