From 9d1042412856ea73d6ff348b95bf5162854f9879 Mon Sep 17 00:00:00 2001 From: bbaia Date: Fri, 21 Jan 2011 17:23:24 +0000 Subject: [PATCH] REST client API: Added tests (SPRNET-1345) --- ...eedHttpMessageConverterIntegrationTests.cs | 4 +- ...sonHttpMessageConverterIntegrationTests.cs | 39 ++- ...XmlHttpMessageConverterIntegrationTests.cs | 6 +- .../Http/Rest/RestTemplateIntegrationTests.cs | 268 +++++++++++++++++- 4 files changed, 295 insertions(+), 22 deletions(-) diff --git a/test/Spring/Spring.Http.Tests/Http/Converters/Feed/FeedHttpMessageConverterIntegrationTests.cs b/test/Spring/Spring.Http.Tests/Http/Converters/Feed/FeedHttpMessageConverterIntegrationTests.cs index 2a274476..bc1b9d82 100644 --- a/test/Spring/Spring.Http.Tests/Http/Converters/Feed/FeedHttpMessageConverterIntegrationTests.cs +++ b/test/Spring/Spring.Http.Tests/Http/Converters/Feed/FeedHttpMessageConverterIntegrationTests.cs @@ -1,4 +1,4 @@ -#if NET_4_0 +#if NET_3_5 #region License /* @@ -123,6 +123,7 @@ namespace Spring.Http.Converters.Feed [ServiceKnownType(typeof(Rss20ItemFormatter))] public class TestService { + [OperationContract] [WebGet(UriTemplate = "feed/", BodyStyle = WebMessageBodyStyle.Bare)] public SyndicationFeedFormatter CreateFeed() { @@ -152,6 +153,7 @@ namespace Spring.Http.Converters.Feed return formatter; } + [OperationContract] [WebInvoke(UriTemplate = "feed/entry")] public void AddEntry(SyndicationItemFormatter item) { diff --git a/test/Spring/Spring.Http.Tests/Http/Converters/Json/JsonHttpMessageConverterIntegrationTests.cs b/test/Spring/Spring.Http.Tests/Http/Converters/Json/JsonHttpMessageConverterIntegrationTests.cs index 22bc7c43..29a1891d 100644 --- a/test/Spring/Spring.Http.Tests/Http/Converters/Json/JsonHttpMessageConverterIntegrationTests.cs +++ b/test/Spring/Spring.Http.Tests/Http/Converters/Json/JsonHttpMessageConverterIntegrationTests.cs @@ -1,4 +1,4 @@ -#if NET_4_0 +#if NET_3_5 #region License /* @@ -55,7 +55,6 @@ namespace Spring.Http.Converters.Json { template = new RestTemplate(uri); template.MessageConverters = new List(); - //template.MessageConverters.Add(new StringHttpMessageConverter()); // for debugging purpose contentType = new MediaType("application", "json"); @@ -69,19 +68,43 @@ namespace Spring.Http.Converters.Json webServiceHost.Close(); } + [Test] + public void GetForJson() + { + template.MessageConverters.Add(new StringHttpMessageConverter()); + + string resultAsString = template.GetForObject("user/{id}", 1); + Assert.AreEqual("{\"ID\":\"1\",\"Name\":\"Bruno Baïa\"}", resultAsString, "Invalid content"); + } + [Test] public void GetForObject() { template.MessageConverters.Add(new JsonHttpMessageConverter()); - User result = template.GetForObject("user/{id}", "1"); + User result = template.GetForObject("user/{id}", 1); Assert.IsNotNull(result, "Invalid content"); Assert.AreEqual("1", result.ID, "Invalid content"); Assert.AreEqual("Bruno Baïa", result.Name, "Invalid content"); } [Test] - public void PostForMessage() + public void PostJsonForMessage() + { + template.MessageConverters.Add(new StringHttpMessageConverter()); + + HttpEntity entity = new HttpEntity("{\"Name\":\"Lisa Baia\"}"); + entity.Headers.ContentType = MediaType.APPLICATION_JSON; + + HttpResponseMessage result = template.PostForMessage("user", entity); + Assert.IsNull(result.Body, "Invalid content"); + Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), result.Headers.Location, "Invalid location"); + Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Invalid status code"); + Assert.AreEqual("User id '3' created with 'Lisa Baia'", result.StatusDescription, "Invalid status description"); + } + + [Test] + public void PostObjectForMessage() { template.MessageConverters.Add(new JsonHttpMessageConverter()); @@ -119,11 +142,11 @@ namespace Spring.Http.Converters.Json users.Add(new User() { ID = "2", Name = "Marie Baia" }); } - [WebGet(UriTemplate = "user/{id}")] + [OperationContract] + [WebGet(UriTemplate = "user/{id}", ResponseFormat = WebMessageFormat.Json)] public User GetUser(string id) { WebOperationContext context = WebOperationContext.Current; - context.OutgoingResponse.Format = WebMessageFormat.Json; foreach (User user in this.users) { @@ -137,11 +160,11 @@ namespace Spring.Http.Converters.Json return null; } - [WebInvoke(UriTemplate = "user", Method = "POST")] + [OperationContract] + [WebInvoke(UriTemplate = "user", Method = "POST", RequestFormat = WebMessageFormat.Json)] public void Create(User user) { WebOperationContext context = WebOperationContext.Current; - context.OutgoingResponse.Format = WebMessageFormat.Json; UriTemplateMatch match = context.IncomingRequest.UriTemplateMatch; UriTemplate template = new UriTemplate("/user/{id}"); diff --git a/test/Spring/Spring.Http.Tests/Http/Converters/Xml/XmlHttpMessageConverterIntegrationTests.cs b/test/Spring/Spring.Http.Tests/Http/Converters/Xml/XmlHttpMessageConverterIntegrationTests.cs index d944ac80..e4e32f11 100644 --- a/test/Spring/Spring.Http.Tests/Http/Converters/Xml/XmlHttpMessageConverterIntegrationTests.cs +++ b/test/Spring/Spring.Http.Tests/Http/Converters/Xml/XmlHttpMessageConverterIntegrationTests.cs @@ -1,4 +1,4 @@ -#if NET_4_0 +#if NET_3_5 #region License /* @@ -143,6 +143,7 @@ namespace Spring.Http.Converters.Xml users.Add(new User() { ID = "2", Name = "Marie Baia" }); } + [OperationContract] [WebGet(UriTemplate = "user/dc/{id}")] public User GetUserDataContract(string id) { @@ -160,6 +161,7 @@ namespace Spring.Http.Converters.Xml return null; } + [OperationContract] [WebInvoke(UriTemplate = "user/dc", Method = "POST")] public void CreateDataContract(User user) { @@ -186,6 +188,7 @@ namespace Spring.Http.Converters.Xml context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", user.ID, user.Name); } + [OperationContract] [WebGet(UriTemplate = "user/xml/{id}")] public XElement GetUserXElement(string id) { @@ -205,6 +208,7 @@ namespace Spring.Http.Converters.Xml return null; } + [OperationContract] [WebInvoke(UriTemplate = "user/xml", Method = "POST")] public void CreateXElement(XElement user) { diff --git a/test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateIntegrationTests.cs b/test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateIntegrationTests.cs index d36466bc..041836da 100644 --- a/test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateIntegrationTests.cs +++ b/test/Spring/Spring.Http.Tests/Http/Rest/RestTemplateIntegrationTests.cs @@ -1,4 +1,4 @@ -#if NET_4_0 +#if NET_3_5 #region License /* @@ -23,6 +23,7 @@ using System; using System.Net; using System.IO; using System.Text; +using System.Threading; using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Web; @@ -67,6 +68,8 @@ namespace Spring.Http.Rest webServiceHost.Close(); } + #region Sync + [Test] public void GetString() { @@ -103,7 +106,7 @@ namespace Spring.Http.Rest { HttpResponseMessage result = template.GetForMessage("user/{id}", 1); Assert.AreEqual("Bruno Baïa", result.Body, "Invalid content"); - Assert.AreEqual(contentType, result.Headers.ContentType, "Invalid content-type"); + Assert.AreEqual(new MediaType("text", "plain", "utf-8"), result.Headers.ContentType, "Invalid content-type"); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode, "Invalid status code"); Assert.AreEqual("OK", result.StatusDescription, "Invalid status description"); } @@ -120,7 +123,7 @@ namespace Spring.Http.Rest public void HeadForHeaders() { HttpHeaders result = template.HeadForHeaders("head"); - Assert.AreEqual(new MediaType("text", "plain"), result.ContentType, "Invalid content-type"); + Assert.AreEqual("MyValue", result["MyHeader"], "Invalid header"); } [Test] @@ -265,6 +268,231 @@ namespace Spring.Http.Rest template.Execute("servererror", HttpMethod.GET, null, null); } + #endregion + + #region Async + + [Test] + public void GetStringAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.GetForObjectAsync("users", + delegate(MethodCompletedEventArgs args) + { + try + { + Assert.IsNull(args.Error, "Invalid response"); + Assert.IsFalse(args.Cancelled, "Invalid response"); + Assert.AreEqual("2", args.Response, "Invalid content"); + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + [Test] + public void GetStringForMessageAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.GetForMessageAsync("user/{id}", + delegate(MethodCompletedEventArgs> args) + { + try + { + Assert.IsNull(args.Error, "Invalid response"); + Assert.IsFalse(args.Cancelled, "Invalid response"); + Assert.AreEqual("Bruno Baïa", args.Response.Body, "Invalid content"); + Assert.AreEqual(new MediaType("text", "plain", "utf-8"), args.Response.Headers.ContentType, "Invalid content-type"); + Assert.AreEqual(HttpStatusCode.OK, args.Response.StatusCode, "Invalid status code"); + Assert.AreEqual("OK", args.Response.StatusDescription, "Invalid status description"); + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }, 1); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + [Test] + public void PostStringForMessageAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.PostForMessageAsync("user", "Lisa Baia", + delegate(MethodCompletedEventArgs> args) + { + try + { + Assert.IsNull(args.Error, "Invalid response"); + Assert.IsFalse(args.Cancelled, "Invalid response"); + Assert.AreEqual(new Uri(new Uri(uri), "/user/3"), args.Response.Headers.Location, "Invalid location"); + Assert.AreEqual(HttpStatusCode.Created, args.Response.StatusCode, "Invalid status code"); + Assert.AreEqual("User id '3' created with 'Lisa Baia'", args.Response.StatusDescription, "Invalid status description"); + Assert.AreEqual("3", args.Response.Body, "Invalid content"); + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + [Test] + public void DeleteAsyncWithNoAction() + { + string result = template.GetForObject("users"); + Assert.AreEqual("2", result, "Invalid content"); + + template.DeleteAsync("user/2", null); + + Thread.Sleep(TimeSpan.FromSeconds(1)); + + result = template.GetForObject("users"); + Assert.AreEqual("1", result, "Invalid content"); + } + + [Test] + public void ExchangeForMessageAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.ExchangeAsync("user/1", HttpMethod.PUT, new HttpEntity("Bruno Baia"), + delegate(MethodCompletedEventArgs args) + { + try + { + Assert.IsNull(args.Error, "Invalid response"); + Assert.IsFalse(args.Cancelled, "Invalid response"); + Assert.AreEqual(HttpStatusCode.OK, args.Response.StatusCode, "Invalid status code"); + Assert.AreEqual("User id '1' updated with 'Bruno Baia'", args.Response.StatusDescription, "Invalid status description"); + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + [Test] + [ExpectedException(typeof(HttpClientErrorException), + ExpectedMessage = "The server returned 'Not Found' with the status code 404 - NotFound.")] + public void ClientErrorAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.ExecuteAsync("clienterror", HttpMethod.GET, null, null, + delegate(MethodCompletedEventArgs args) + { + try + { + Assert.IsFalse(args.Cancelled, "Invalid response"); + + Assert.IsNotNull(args.Error, "Invalid response"); + exception = args.Error; + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + [Test] + [ExpectedException(typeof(HttpServerErrorException), + ExpectedMessage = "The server returned 'Internal Server Error' with the status code 500 - InternalServerError.")] + public void ServerErrorAsync() + { + ManualResetEvent manualEvent = new ManualResetEvent(false); + Exception exception = null; + + template.ExecuteAsync("servererror", HttpMethod.GET, null, null, + delegate(MethodCompletedEventArgs args) + { + try + { + Assert.IsFalse(args.Cancelled, "Invalid response"); + + Assert.IsNotNull(args.Error, "Invalid response"); + exception = args.Error; + } + catch (Exception ex) + { + exception = ex; + } + finally + { + manualEvent.Set(); + } + }); + + manualEvent.WaitOne(); + if (exception != null) + { + throw exception; + } + } + + #endregion + #region REST test service [ServiceContract] @@ -280,60 +508,68 @@ namespace Spring.Http.Rest users.Add("2", "Marie Baia"); } + [OperationContract] [WebGet(UriTemplate = "clienterror")] public void ClientError() { WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound(); } + [OperationContract] [WebGet(UriTemplate = "servererror")] public void ServerError() { WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError; } + [OperationContract] [WebInvoke(UriTemplate = "allow", Method = "OPTIONS")] public void Allow() { WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.Allow] = "GET, HEAD, PUT"; } + [OperationContract] [WebInvoke(UriTemplate = "head", Method = "HEAD")] public void Head() { - WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.ContentType] = "text/plain"; + WebOperationContext.Current.OutgoingResponse.Headers["MyHeader"] = "MyValue"; } + [OperationContract] [WebGet(UriTemplate = "user/{id}")] - public Message GetUser(string id) + public Stream GetUser(string id) { WebOperationContext context = WebOperationContext.Current; if (!users.ContainsKey(id)) { context.OutgoingResponse.SetStatusAsNotFound(String.Format("User with id '{0}' not found", id)); - return context.CreateTextResponse(null); + return null; } - return context.CreateTextResponse(users[id]); + return CreateTextResponse(context, users[id]); } + [OperationContract] [WebGet(UriTemplate = "users")] - public Message GetUsersCount() + public Stream GetUsersCount() { WebOperationContext context = WebOperationContext.Current; - return context.CreateTextResponse(users.Count.ToString()); + return CreateTextResponse(context, users.Count.ToString()); } + [OperationContract] [WebGet(UriTemplate = "nothing")] public void GetNothing() { WebOperationContext.Current.OutgoingResponse.SuppressEntityBody = true; } + [OperationContract] [WebInvoke(UriTemplate = "user", Method = "POST")] - public Message Post(Stream stream) + public Stream Post(Stream stream) { WebOperationContext context = WebOperationContext.Current; @@ -354,7 +590,7 @@ namespace Spring.Http.Rest { context.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest; context.OutgoingResponse.StatusDescription = "Content cannot be null or empty"; - return WebOperationContext.Current.CreateTextResponse(""); + return CreateTextResponse(context, ""); } users.Add(id, name); @@ -363,9 +599,10 @@ namespace Spring.Http.Rest context.OutgoingResponse.SetStatusAsCreated(uri); context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' created with '{1}'", id, name); - return WebOperationContext.Current.CreateTextResponse(id); + return CreateTextResponse(context, id); } + [OperationContract] [WebInvoke(UriTemplate = "user/{id}", Method = "PUT")] public void Update(string id, Stream stream) { @@ -391,6 +628,7 @@ namespace Spring.Http.Rest context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' updated with '{1}'", id, name); } + [OperationContract] [WebInvoke(UriTemplate = "user/{id}", Method = "DELETE")] public void Delete(string id) { @@ -408,6 +646,12 @@ namespace Spring.Http.Rest context.OutgoingResponse.StatusCode = HttpStatusCode.OK; context.OutgoingResponse.StatusDescription = String.Format("User id '{0}' have been removed", id); } + + private Stream CreateTextResponse(WebOperationContext context, string text) + { + context.OutgoingResponse.ContentType = "text/plain; charset=utf-8"; + return new MemoryStream(Encoding.UTF8.GetBytes(text)); + } } #endregion