问题
I'm writing unit tests for some of the web services we've developed. I have a [TestMethod] that posts to a webservice as rest. Works great however it doesn't trigger the eventhandler method that I created. Through debugging, I've noticed that the eventhandler is getting excluder after the testmethod is executed. It goes to testcleanup.
Has anyone encountered this problem? Here's the code
[TestMethod,TestCategory("WebServices")]
public void ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var _requestclient = new WebClient())
{
_requestclient.UploadStringCompleted += _requestclient_UploadStringCompleted;
var _uri = String.Format("{0}?format=Json", _webservicesurl);
_requestclient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
_requestclient.UploadStringAsync(new Uri(_uri), "POST", _jsonstringparams);
}
}
void _requestclient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Result != null)
{
var _responsecontent = e.Result.ToString();
Console.WriteLine(_responsecontent);
}
else
{
Assert.IsNotNull(e.Error.Message, "Test Case Failed");
}
}
回答1:
The problem is is that UploadStringAsync returns void (i.e. it's fire and forget) and doesn't inherently let you detect completion.
There's a couple of options. The first option (which is the one I'd recommend) is to use HttpClient instead and use the PostAsync method--which you can await
. In which case, I'd do something like this:
[TestMethod, TestCategory("WebServices")]
public async Task ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var httpClient = new HttpClient())
{
var _uri = String.Format("{0}?format=Json", _webservicesurl);
var stringContent = new StringContent(_jsonstringparams);
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(_uri, stringContent);
// Or whatever status code this service response with
Assert.AreEqual(HttpStatusCode.Accepted, response.StatusCode);
var responseText = await response.Content.ReadAsStringAsync();
// TODO: something more specific to your needs
Assert.IsTrue(!string.IsNullOrWhiteSpace(responseText));
}
}
The other option is to change your complete event handler to signal back to your test that the upload is completed and in your test, wait for the event to occur. For example:
[TestMethod, TestCategory("WebServices")]
public void ValidateWebServiceGetUserAuthToken()
{
string _jsonstringparams =
"{ \"Password\": \"xxx\", \"UserId\": \"xxxx\"}";
using (var _requestclient = new WebClient())
{
_requestclient.UploadStringCompleted += _requestclient_UploadStringCompleted;
var _uri = String.Format("{0}?format=Json", _webservicesurl);
_requestclient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
_requestclient.UploadStringAsync(new Uri(_uri), "POST", _jsonstringparams);
completedEvent.WaitOne();
}
}
private ManualResetEvent completedEvent = new ManualResetEvent(false);
void _requestclient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Result != null)
{
var _responsecontent = e.Result.ToString();
Console.WriteLine(_responsecontent);
}
else
{
Assert.IsNotNull(e.Error.Message, "Test Case Failed");
}
completedEvent.Set();
}
回答2:
Besides the answers posts above, I've also added a method to support httpwebresponse so I don't have to wait for the event.
public static AuthTokenResponse GetUserToken(string username, string password)
{
string _jsonstringparams =
String.Format("{{ \"Password\": \"{0}\", \"UserId\": \"{1}\"}}", password, username);
string _webservicesurl = ConfigurationManager.AppSettings["WebservicesUrl"];
HttpWebRequest _requestclient = (HttpWebRequest)WebRequest.Create(String.Format("{0}?format=Json", _webservicesurl));
_requestclient.ContentType = "application/json";
_requestclient.Method = "POST";
using (var streamWriter = new StreamWriter(_requestclient.GetRequestStream()))
{
streamWriter.Write(_jsonstringparams);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)_requestclient.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
_responsecontent = streamReader.ReadToEnd();
}
AuthTokenResponse _clienttoken = JsonConvert.DeserializeObject<AuthTokenResponse>(_responsecontent);
return _clienttoken;
}
}
来源:https://stackoverflow.com/questions/26167133/webclient-uploadstringcompleted-event-not-being-called