Skip to content

Commit a98265a

Browse files
Add initial tests
1 parent 67dfdae commit a98265a

File tree

7 files changed

+272
-51
lines changed

7 files changed

+272
-51
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ CSharpHTTPClient/bin/
33
Example/bin/
44
CSharpHTTPClient/obj/
55
Example/obj/
6-
CSharpHTTPClient/Tests/bin/
7-
CSharpHTTPClient/Tests/obj/
6+
UnitTest/bin/
7+
UnitTest/obj/
88
*.suo
99
CSharpHTTPClient/*/bin/
1010
CSharpHTTPClient/*/obj/

CSharpHTTPClient/CSharpHTTPClient.sln

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpHTTPClient", "CSharpH
77
EndProject
88
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "..\Example\Example.csproj", "{490AD14D-B821-435A-BEC8-F4DFE34E6556}"
99
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTest", "..\UnitTest\UnitTest.csproj", "{DF845C59-4B39-4A8A-AC89-E5336B57076B}"
11+
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1214
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
2123
{490AD14D-B821-435A-BEC8-F4DFE34E6556}.Debug|Any CPU.Build.0 = Debug|Any CPU
2224
{490AD14D-B821-435A-BEC8-F4DFE34E6556}.Release|Any CPU.ActiveCfg = Release|Any CPU
2325
{490AD14D-B821-435A-BEC8-F4DFE34E6556}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{DF845C59-4B39-4A8A-AC89-E5336B57076B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{DF845C59-4B39-4A8A-AC89-E5336B57076B}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{DF845C59-4B39-4A8A-AC89-E5336B57076B}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{DF845C59-4B39-4A8A-AC89-E5336B57076B}.Release|Any CPU.Build.0 = Release|Any CPU
2430
EndGlobalSection
2531
GlobalSection(SolutionProperties) = preSolution
2632
HideSolutionNode = FALSE

CSharpHTTPClient/Client.cs

+56-46
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading.Tasks;
1010
using System.Web.Script.Serialization;
1111
using System.Web;
12+
using System.Diagnostics;
1213

1314
namespace SendGrid.CSharp.HTTP.Client
1415
{
@@ -17,43 +18,39 @@ public class Response
1718
public HttpStatusCode StatusCode;
1819
public HttpContent ResponseBody;
1920
public HttpResponseHeaders ResponseHeaders;
20-
public Dictionary<string, dynamic> DSResponseBody;
21-
public Dictionary<string, string> DSResponseHeaders;
2221

2322
public Response(HttpStatusCode statusCode, HttpContent responseBody, HttpResponseHeaders responseHeaders)
2423
{
2524
StatusCode = statusCode;
2625
ResponseBody = responseBody;
2726
ResponseHeaders = responseHeaders;
28-
DSResponseBody = DeserializeResponseBody(responseBody);
29-
DSResponseHeaders = DeserializeResponseHeaders(responseHeaders);
3027
}
3128

32-
public Dictionary<string, dynamic> DeserializeResponseBody(HttpContent content)
29+
public virtual Dictionary<string, dynamic> DeserializeResponseBody(HttpContent content)
3330
{
3431
JavaScriptSerializer jss = new JavaScriptSerializer();
35-
var ds_content = jss.Deserialize<Dictionary<string, dynamic>>(content.ReadAsStringAsync().Result);
36-
return ds_content;
32+
var dsContent = jss.Deserialize<Dictionary<string, dynamic>>(content.ReadAsStringAsync().Result);
33+
return dsContent;
3734
}
3835

39-
public Dictionary<string, string> DeserializeResponseHeaders(HttpResponseHeaders content)
36+
public virtual Dictionary<string, string> DeserializeResponseHeaders(HttpResponseHeaders content)
4037
{
41-
var ds_content = new Dictionary<string, string>();
38+
var dsContent = new Dictionary<string, string>();
4239
foreach (var pair in content )
4340
{
44-
ds_content.Add(pair.Key, pair.Value.First());
41+
dsContent.Add(pair.Key, pair.Value.First());
4542
}
46-
return ds_content;
43+
return dsContent;
4744
}
4845

4946
}
5047

5148
public class Client : DynamicObject
5249
{
53-
private string _host;
54-
private Dictionary <string,string> _requestHeaders;
55-
private string _version;
56-
private string _urlPath;
50+
public string Host;
51+
public Dictionary <string,string> RequestHeaders;
52+
public string Version;
53+
public string UrlPath;
5754
public string MediaType;
5855
public enum Methods
5956
{
@@ -62,26 +59,26 @@ public enum Methods
6259

6360
public Client(string host, Dictionary<string,string> requestHeaders = null, string version = null, string urlPath = null)
6461
{
65-
_host = host;
62+
Host = host;
6663
if(requestHeaders != null)
6764
{
68-
_requestHeaders = (_requestHeaders != null)
69-
? _requestHeaders.Union(requestHeaders).ToDictionary(pair => pair.Key, pair => pair.Value) : requestHeaders;
65+
RequestHeaders = (RequestHeaders != null)
66+
? RequestHeaders.Union(requestHeaders).ToDictionary(pair => pair.Key, pair => pair.Value) : requestHeaders;
7067
}
71-
_version = (version != null) ? version : null;
72-
_urlPath = (urlPath != null) ? urlPath : null;
68+
Version = (version != null) ? version : null;
69+
UrlPath = (urlPath != null) ? urlPath : null;
7370
}
7471

7572
private string BuildUrl(string query_params = null)
7673
{
7774
string endpoint = null;
78-
if( _version != null)
75+
if( Version != null)
7976
{
80-
endpoint = _host + "/" + _version + _urlPath;
77+
endpoint = Host + "/" + Version + UrlPath;
8178
}
8279
else
8380
{
84-
endpoint = _host + _urlPath;
81+
endpoint = Host + UrlPath;
8582
}
8683

8784
if (query_params != null)
@@ -105,19 +102,25 @@ private Client BuildClient(string name = null)
105102
string endpoint;
106103
if (name != null)
107104
{
108-
endpoint = _urlPath + "/" + name;
105+
endpoint = UrlPath + "/" + name;
109106
}
110107
else
111108
{
112-
endpoint = _urlPath;
109+
endpoint = UrlPath;
113110
}
114-
_urlPath = null; // Reset the current object's state before we return a new one
115-
return new Client(_host, _requestHeaders, _version, endpoint);
111+
UrlPath = null; // Reset the current object's state before we return a new one
112+
return new Client(Host, RequestHeaders, Version, endpoint);
116113
}
117114

118-
private void AddVersion(string version)
115+
public virtual AuthenticationHeaderValue AddAuthorization(KeyValuePair<string, string> header)
119116
{
120-
_version = version;
117+
string[] split = header.Value.Split(new char[0]);
118+
return new AuthenticationHeaderValue(split[0], split[1]);
119+
}
120+
121+
public virtual void AddVersion(string version)
122+
{
123+
Version = version;
121124
}
122125

123126
// Magic method to handle special cases
@@ -171,7 +174,13 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
171174
result = null;
172175
return false;
173176
}
174-
177+
178+
}
179+
180+
public async virtual Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request)
181+
{
182+
HttpResponseMessage response = await client.SendAsync(request);
183+
return new Response(response.StatusCode, response.Content, response.Headers);
175184
}
176185

177186
private async Task<Response> RequestAsync(string method, String request_body = null, String query_params = null)
@@ -180,24 +189,26 @@ private async Task<Response> RequestAsync(string method, String request_body = n
180189
{
181190
try
182191
{
183-
client.BaseAddress = new Uri(_host);
192+
client.BaseAddress = new Uri(Host);
184193
string endpoint = BuildUrl(query_params);
185194
client.DefaultRequestHeaders.Accept.Clear();
186-
foreach (KeyValuePair<string, string> header in _requestHeaders)
195+
if(RequestHeaders != null)
187196
{
188-
if(header.Key == "Authorization")
189-
{
190-
string[] split = header.Value.Split(new char[0]);
191-
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(split[0], split[1]); ;
192-
}
193-
else if(header.Key == "Content-Type")
197+
foreach (KeyValuePair<string, string> header in RequestHeaders)
194198
{
195-
MediaType = header.Value;
196-
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
197-
}
198-
else
199-
{
200-
client.DefaultRequestHeaders.Add(header.Key, header.Value);
199+
if (header.Key == "Authorization")
200+
{
201+
client.DefaultRequestHeaders.Authorization = AddAuthorization(header);
202+
}
203+
else if (header.Key == "Content-Type")
204+
{
205+
MediaType = header.Value;
206+
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
207+
}
208+
else
209+
{
210+
client.DefaultRequestHeaders.Add(header.Key, header.Value);
211+
}
201212
}
202213
}
203214

@@ -213,8 +224,7 @@ private async Task<Response> RequestAsync(string method, String request_body = n
213224
RequestUri = new Uri(endpoint),
214225
Content = content
215226
};
216-
HttpResponseMessage response = await client.SendAsync(request);
217-
return new Response(response.StatusCode, response.Content, response.Headers);
227+
return await MakeRequest(client, request);
218228

219229
}
220230
catch (Exception ex)

Example/Example.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ static void Main(string[] args)
2626
//Console.WriteLine(response.StatusCode);
2727
//Console.WriteLine(response.ResponseBody.ReadAsStringAsync().Result);
2828
//Console.WriteLine(response.ResponseHeaders.ToString());
29-
30-
foreach ( var value in response.DSResponseBody["result"])
29+
var dssResponseBody = response.DeserializeResponseBody(response.ResponseBody);
30+
foreach ( var value in dssResponseBody["result"])
3131
{
3232
Console.WriteLine("name: {0}, api_key_id: {1}",value["name"], value["api_key_id"]);
3333
}
34-
foreach (var pair in response.DSResponseHeaders)
34+
var dssResponseHeaders = response.DeserializeResponseHeaders(response.ResponseHeaders);
35+
foreach (var pair in dssResponseHeaders)
3536
{
3637
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
3738
}

UnitTest/Properties/AssemblyInfo.cs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("UnitTest")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("UnitTest")]
13+
[assembly: AssemblyCopyright("Copyright © 2016")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("df845c59-4b39-4a8a-ac89-e5336b57076b")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

UnitTest/UnitTest.cs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using SendGrid.CSharp.HTTP.Client;
4+
using System.Collections.Generic;
5+
using System.Threading.Tasks;
6+
using System.Net.Http;
7+
using System.Text;
8+
using System.Net;
9+
using System.Diagnostics;
10+
11+
namespace UnitTest
12+
{
13+
public class MockClient : Client
14+
{
15+
public MockClient(string host, Dictionary<string, string> requestHeaders = null, string version = null, string urlPath = null) : base (host, requestHeaders, version, urlPath)
16+
{
17+
}
18+
19+
public async override Task<Response> MakeRequest(HttpClient client, HttpRequestMessage request)
20+
{
21+
HttpResponseMessage response = new HttpResponseMessage();
22+
response.Content = new StringContent("{'test': 'test_content'}", Encoding.UTF8, "application/json");
23+
response.StatusCode = HttpStatusCode.OK;
24+
return new Response(response.StatusCode, response.Content, response.Headers);
25+
}
26+
}
27+
28+
[TestClass]
29+
public class TestClient
30+
{
31+
[TestMethod]
32+
public void TestInitialization()
33+
{
34+
var host = "http://api.test.com";
35+
Dictionary<String, String> requestHeaders = new Dictionary<String, String>();
36+
var version = "v3";
37+
var urlPath = "/test/url/path";
38+
var test_client = new MockClient(host: host, requestHeaders: requestHeaders, version: version, urlPath: urlPath);
39+
requestHeaders.Add("Authorization", "Bearer SG.XXXX");
40+
requestHeaders.Add("Content-Type", "application/json");
41+
requestHeaders.Add("X-TEST", "test");
42+
Assert.IsNotNull(test_client);
43+
Assert.AreEqual(host, test_client.Host);
44+
Assert.AreEqual(requestHeaders, test_client.RequestHeaders);
45+
Assert.AreEqual(version, test_client.Version);
46+
Assert.AreEqual(urlPath, test_client.UrlPath);
47+
}
48+
49+
[TestMethod]
50+
public void TestReflection()
51+
{
52+
var host = "http://api.test.com";
53+
dynamic test_client = new MockClient(host: host);
54+
dynamic url1 = test_client.my.test.path;
55+
Assert.AreEqual(url1.UrlPath, "/my/test/path");
56+
url1 = test_client.my._("test").path;
57+
Assert.AreEqual(url1.UrlPath, "/my/test/path");
58+
url1 = test_client.version("v4").my.test.path;
59+
Assert.AreEqual(url1.Version, "v4");
60+
Assert.AreEqual(url1.UrlPath, "/my/test/path");
61+
url1 = url1.final.result;
62+
Assert.AreEqual(url1.UrlPath, "/my/test/path/final/result");
63+
}
64+
65+
[TestMethod]
66+
public void TestMethodCall()
67+
{
68+
var host = "http://api.test.com";
69+
dynamic test_client = new MockClient(host: host);
70+
Response response = test_client.get();
71+
Assert.IsNotNull(response);
72+
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
73+
var content = new StringContent("{'test': 'test_content'}", Encoding.UTF8, "application/json");
74+
Assert.AreEqual(response.ResponseBody.ReadAsStringAsync().Result, content.ReadAsStringAsync().Result);
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)