As Richard Willis suggests in http://blog.salamandersoft.co.uk/index.php/2009/10/how-to-mock-httpwebrequest-when-unit-testing/ i'm trying to call a web request moking the behavior.
For that (I asking me if I'm messing something here) I implemented an IWebRequestCreate and extended a WebRequest and a WebResponse. (more details in link codes)
But now in my code I had a test that register (WebRequest.RegisterPrefix) a prefix:
[Test]
public void Test() {
var some = File.ReadAllBytes(#"TestData\WebService\admrond_13jan2011_14jan2011.xml");
WebRequest.RegisterPrefix("mockPrefix", new WebRequestCreateMock());
WebRequestFake request = WebRequestCreateMock.CreateRequestFake(some);
_remoteRepository.PopulateWithMeterData(_meter);
... (error in line before)
Then, I got this error: Invalid URI: The hostname could not be parsed.
But why? In my PopulateWithMeterData(Meter meter) I have this call:
WebRequest request = WebRequest.Create(urlListMeteringData);
WebResponse ws = request.GetResponse();
Some suggestion? Is interesting post my class implementations?
EDIT: as #Matthew ask:
public class WebRequestCreateMock : IWebRequestCreate {
static WebRequest _nextRequest;
static readonly object LockObject = new object();
static public WebRequest NextRequest {
get { return _nextRequest; }
set {
lock (LockObject) {
_nextRequest = value;
}
}
}
public WebRequest Create(Uri uri) {
return _nextRequest;
}
public static WebRequestFake CreateRequestFake(byte[] xmlStream) {
WebRequestFake webRequestFake = new WebRequestFake(xmlStream);
NextRequest = webRequestFake;
return webRequestFake;
}
}
public class WebRequestFake : WebRequest {
MemoryStream requestStream = new MemoryStream();
MemoryStream responseStream;
public override string Method { get; set; }
public override string ContentType { get; set; }
public override long ContentLength { get; set; }
public WebRequestFake(byte[] response) {
responseStream = new MemoryStream(response);
}
public override Stream GetRequestStream() {
return requestStream;
}
public override WebResponse GetResponse() {
return new WebReponseFake(responseStream);
}
}
public class WebReponseFake : WebResponse {
private readonly Stream _responseStream;
public WebReponseFake(Stream responseStream) {
_responseStream = responseStream;
}
public override Stream GetResponseStream() {
return _responseStream;
}
}
And the Url is something like: mockPrefix://NoMatterUrl
Since the error is "Invalid URI: The hostname could not be parsed." you are probably screwing up your Uri "mockPrefix://NoMatterUrl"
I had this problem once because I forgot to add a "/" between the domain uri and the request parameters.
Can you post exactly what your "NoMatterUri" looks like?
You need to register your prefix with a colon (':'); as in:
WebRequest.RegisterPrefix("mockPrefix:", new WebRequestCreateMock());
I have found that it's necessary to include a trailing "/" in the prefix. For instance, "test://localhost/":
[TestClass]
public class WebRequestTests
{
[TestMethod]
public void TestWebRequestCreate()
{
const string uriString = "test://localhost/foo/bar.baz?a=b&c=d";
var webRequest = new MockWebRequestCreateAssertUrl(uriString);
Assert.IsTrue(WebRequest.RegisterPrefix("test://localhost/", webRequest),
"Failed to register prefix");
Assert.IsNotNull(WebRequest.Create(uriString));
}
public class MockWebRequestCreateAssertUrl : IWebRequestCreate
{
private readonly Uri _expectedUri;
public MockWebRequestCreateAssertUrl(string uriString)
{
_expectedUri = new Uri(uriString);
}
public WebRequest Create(Uri uri)
{
Assert.AreEqual(_expectedUri, uri, "uri parameter is wrong");
return new MockWebRequestAssertUrl();
}
}
public class MockWebRequestAssertUrl : WebRequest {}
}
Related
I have some legacy code that I'm trying to work with and need to return an existing object that contains a Stream from an ApiController
public class LegacyObject
{
public bool Result { get; set; }
public Stream Stream { get; set; }
}
API Code
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string rawRequest;
using (var stream = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result))
{
stream.BaseStream.Position = 0;
rawRequest = stream.ReadToEnd();
}
rawRequest = rawRequest.ToString();
var obj = JsonConvert.DeserializeObject<LegacyParameters>(rawRequest.ToString());
actionContext.ActionArguments["parameter"] = obj;
}
}
public class ReportsController : ApiController
{
[BindJson]
[HttpPost]
public LegacyObject ReturnReport([FromBody]LegacyParameters parameter)
{
LegacyObject r = LegacyClass.GetReportStream(parameters);
return r; //Object properties are correctly set and no errors at this point
}
}
My call to the Api is
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.BaseAddress = new Uri("http://myserver/");
string contents = JsonConvert.SerializeObject(paramList);
var response = httpClient.PostAsync("/api/ReturnReport", new StringContent(contents, Encoding.UTF8, "application/json")).Result;
}
I get a 500 Internal Server Error on the PostAsync when my LegacyObject.Stream has content. It works when the stream content is null. I'm working locally on my development PC and web server for the API is IIS Express.
Any advice would be appreciated.
So in order to get more detail on the 500 Internal Server Error, I added this to my projects WebApiConfig Register
config.Services.Replace(typeof(IExceptionLogger), new UnhandledExceptionLogger());
With this class
public class UnhandledExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
var log = context.Exception.ToString();
//Write the exception to your logs
}
}
The log variable now gives me the detail I need to debug
FYI - The error was a read timeout on my Stream
How can I do a GET using Windows Phone based on my Web API code? To make a Post i already know and Works for me, but i don't know to retrieve a list of Collections from my API, Thanks!
My API Code:
public class UsersController : ApiController
{
private ApiDatabaseEntities data = new ApiDatabaseEntities();
public IHttpActionResult GetUsuarios()
{
try
{
IEnumerable<Usuario> usuarios = data.Usuario.AsEnumerable();
return Ok(usuarios.AsEnumerable());
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
public IHttpActionResult PostUsuarios(Usuario usuario)
{
try
{
data.Usuario.Add(usuario);
data.SaveChanges();
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
And here is my Windows phone code:
1 - WebApiBase
public abstract class WebApiBase<T>
{
private string Url = "http://localhost:63964/api/users";
protected virtual void Post(object objectPost)
{
HttpClient client = new HttpClient();
client.PostAsJsonAsync(Url, objectPost);
}
public abstract void Send(T objectPost);
}
2 - And UsuarioApi
public class UsuarioApi : WebApiBase<Models.UserPhone>
{
public override void Send(UserPhone objectPost)
{
this.Post(objectPost);
}
}
For Sending get request to server from Windows Phone and then handling the response from server.
public async void GetRequest(){ string url = "APIurl";
HttpClient _client = new HttpClient();
HttpResponseMessage _response = await _client.GetAsync(new Uri(url));
if (_response.IsSuccessStatusCode)
{
string APIResponse = await _response.Content.ReadAsStringAsync();
var myObject = Newtonsoft.Json.Linq.JArray.Parse(APIResponse).ToObject<MyClass>();
}
}
and MyClass
public class MyClass
{
public ObservableCollection<CollectionClass> _myCollection{get;set;}
}
public class CollectionClass
{
public string Name{get;set;}
}
and now You can perform operations on myObject as per your requirement.
I've implemented a command pattern in a project I'm working on. This is pretty much the current structure:
public class Response
{
public bool Success { get; private set; }
public static Response CreateErrorResponse()
{
return new Response { Success = false };
}
}
public interface ICommand<T> where T : Response
{
Task<T> ExecuteAsync();
}
public abstract CommandBase : ICommand<T> where T: Response
{
protected abstract Uri BuildUrl();
protected abstract Task<T> HandleResponseAsync();
public async override Task<T> ExecuteAsync()
{
var url = BuildUrl();
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
return await HandleResponseAsync(response);
}
}
I want to handle any exceptions that could be thrown by the HttpClient, so I want to change CommandBase.ExecuteAsync to something like this...
public async override Task<T> ExecuteAsync()
{
var url = BuildUrl();
var httpClient = new HttpClient();
try
{
var response = await httpClient.GetAsync(url);
return await HandleResponseAsync(response);
}
catch (HttpRequestException hex)
{
return Response.CreateErrorResponse(); // doesn't compile
}
}
The compile error I get is "Cannot convert type Response to async return type T". I can't use T.CreateErrorResponse(), as outlined in this question.
How can I work around this?
Edit to downvoters: whether or not you agree with catching exceptions in a library like this, the question still stands!
Although I am not sure this is the best solution (or feasible in your specific use case), what you can do is:
public class Response
{
public bool Success { get; private set; }
public ExceptionDispatchInfo ErrorInfo { get; private set; }
public bool HasFailed
{
get { return !Success; }
}
public static T CreateErrorResponse<T>(ExceptionDispatchInfo errorInfo) where T : Response, new()
{
var response = new T();
response.Success = false;
response.ErrorInfo = errorInfo;
return response;
}
}
Usage:
catch (HttpRequestException hex)
{
return Response.CreateErrorResponse<T>(ExceptionDispatchInfo.Capture(hex)); // should compile (I did not check)
}
You can cast the response to T. EDIT: Added full source code
public class Response
{
public bool Success { get; private set; }
public static Response CreateErrorResponse()
{
return new Response { Success = false };
}
}
public interface ICommand<T> where T : Response
{
Task<T> ExecuteAsync();
}
public abstract class CommandBase<T> : ICommand<T> where T: Response
{
protected abstract Uri BuildUrl();
protected abstract Task<T> HandleResponseAsync();
public async Task<T> ExecuteAsync()
{
var url = BuildUrl();
var httpClient = new System.Net.Http.HttpClient();
try
{
var response = await httpClient.GetAsync(url);
return null;// await HandleResponseAsync(response);
}
catch (Exception hex)
{
return (T)Response.CreateErrorResponse(); // doesn't compile
}
}
}
public async override Task<T> ExecuteAsync()
{
var url = BuildUrl();
var httpClient = new HttpClient();
try
{
var response = await httpClient.GetAsync(url);
return await HandleResponseAsync(response);
}
catch (HttpRequestException hex)
{
return (T)Response.CreateErrorResponse(); // compiles on liqpad
}
}
I've been struggling for a while now, but I just can't get this work. I'm trying to download a json string to my Windows Phone 8 application, by using the 'sort of' async await.
I'm using the promising solution of Matthias Shapiro.
HttpExtensions.cs
public static class HttpExtensions
{
public static Task<Stream> GetRequestStreamAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<Stream>();
request.BeginGetRequestStream(ar =>
{
Stream requestStream = request.EndGetRequestStream(ar);
taskComplete.TrySetResult(requestStream);
}, request);
return taskComplete.Task;
}
public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
}
public static class HttpMethod
{
public static string Head { get { return "HEAD"; } }
public static string Post { get { return "POST"; } }
public static string Put { get { return "PUT"; } }
public static string Get { get { return "GET"; } }
public static string Delete { get { return "DELETE"; } }
public static string Trace { get { return "TRACE"; } }
public static string Options { get { return "OPTIONS"; } }
public static string Connect { get { return "CONNECT"; } }
public static string Patch { get { return "PATCH"; } }
}
And My MainPageViewModel.cs
protected override void OnActivate()
{
base.OnActivate();
GetSessions();
}
private async void GetSessions()
{
var result = await GetMyData("http://localhost/api/MyData");
}
public async Task<string> GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = HttpMethod.Get;
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
using (var sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
Once it hits the "HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);", I'm getting a WebException:
"System.Net.WebException: The remote server returned an error: NotFound"
When I dive a bit deeper, I notice this error isn't the actual error. When I check the "asyncResponse" inside the GetResponseAsync method in the HttpExtensions class I notice the error:
"AsyncWaitHandle = 'asyncResponse.AsyncWaitHandle' threw an exception of type 'System.NotSupportedException'"
I have no idea how to get this work. Is it something I'm doing wrong?
I see the problem now. Since the emulator is using a virtual machine you cannot use localhost because localhost is the phone and not your PC. See this solution: Windows Phone 8 Emulator: Access localhost
I want to test a class that via a Webrequest sends texts, how can I using Moq mock the GetRequest methode, to test the GetRequest?
public class Sender
public void Send(string Message)
{
...
WebRequest myReq = GetRequest(sParmeter);
}
protected WebRequest GetRequest(string URl)
{
return WebRequest.Create(URl);
}
}
For something like this, the easy way would be to move your WebRequest instance and its action behind an interfaced intermediary.
Example:
public interface IWebRequestHandler
{
WebRequest GetRequest (string URI);
}
public class WebRequestHandler : IWebRequestHandler
{
public WebRequest GetRequest (string URI)
{
return WebRequest.Create(URl);
}
}
Your sender class should have an injectable instance of IWebRequestHandler and you can mock it with MOQ, set up expctations, verify it gets called and anything else you might want.
public class Sender
{
public IWebRequestHandler Handler{get;set;}
public void Send(string Message)
{
Handler.GetRequest(new URI(Message));//call the method with right params, just an example
}
}
One of the approaches that I was gonna suggest is the same as the response by AD.Net, but if you do not wish to modify your existing structure and still test you could do something like below:
Modify your original class as follows:
public class Sender
{
public void Send(string Message)
{
...
WebRequest myReq = GetRequest(sParmeter);
}
protected virtual WebRequest GetRequest(string URl)
{
return WebRequest.Create(URl);
}
}
and in your test project extend this class as follows:
public class MockSender: Sender
{
private WebRequest _response;
public MockSender(WebRequest response)
{
_response=response; //initialize data to be returned
}
protected override WebRequest GetRequest(string URl)
{
//return your test;
}
}
and now in your test create an instance of type MockSender and call the Send method on it.
Moq expects your class to be abstract or you to implement an interface and thus mock the interface which is what AD.Net has described
Hope this helps..
Alternative is to pass the IWebRequestCreate method in to the constructor.
public HTTPRequestFactory(IWebRequestCreate create)
{
_IWebRequestCreate = create;
}
public HTTPRequestFactory()
{
//Do nothing this is the real constructor, above is just for testing.
}
public WebRequest Create(String uri)
{
Uri _uri = new Uri("http://"+this.address+uri);
request = (HttpWebRequest)this.Create(_uri);
return request;
}
public WebRequest Create(Uri uri)
if (null == _IWebRequestCreate)
{
//use the real one
request = WebRequest.Create(uri);
}
else
{
//testing so use test one
request = _IWebRequestCreate.Create(uri);
}
return request;
}
}
Then you can use a standard test to confirm it gets called like you want.
[Test]
public void NewwebrequestCreatesWebRequest()
{
var mockCreate = new Mock<IWebRequestCreate>();
mockCreate.Setup(x => x.Create(It.IsAny<Uri>()));
HTTPRequestFactory webrequest = new HTTPRequestFactory(mockCreate.Object);
HttpWebRequest request = (HttpWebRequest)webrequest.Create(testURI);
mockCreate.VerifyAll();
}
[Test]
public void webrequestUsesAddressProperty()
{
var mockCreate = new Mock<IWebRequestCreate>();
string IP = "10.99.99.99";
Uri expected = new Uri("http://10.99.99.99/services");
mockCreate.Setup(x => x.Create(expected));
HTTPRequestFactory webrequest = new HTTPRequestFactory(mockCreate.Object);
webrequest.address = IP;
HttpWebRequest request = (HttpWebRequest)webrequest.Create(testURI);
mockCreate.VerifyAll();
}
The reason for two Create functions is that you want to pass in a string Create(string) and IWebRequestCreate requires a Create(Uri).
Edited because standard dependancy injection does not work with IWebRequestCreate. Standard pattern is Instantiate an object with the Interface and pass it in through the constructor. Since WebRequest cannot be created with a constructor and interfaces canot be instantiated, the above logic works around that.