I’m about to start work on an OpenRasta project (an xml over http web service). OpenRasta looks great but unfortunately worked examples seem few and far between on the internet. Looking at the test side of the project, if my handlers are returning strongly typed objects (not OperationResult), i.e.:
public class PersonHandler
...
public Person Get(int id)
{
...
How can I test for http status codes? (For example if the handler throws an uncaught exception). I’m not sure what level the tests pitch in at, and what needs mocking (using moq btw)
Any help appreciated, particularly coded examples!
I faced the same problem, and ended up writing my tests as integration tests at a much higher level, actually making real REST/HTTP calls through a simple HttpWebRequest client. This allowed me to check the HTTP response headers / status codes and double-check the JSON/XML serialization from the client's perspective, which was just as important as whether or not the operations succeeded.
I started by returning OperationResult from all my handlers, and used these to wrap the strongly-typed objects. My handlers all inherit from a base class with a few helper methods that make it easier to return a custom error with a user-friendly error message. The more I coded this up, the more my handlers resembled a ASP.NET MVC controller. e.g.:
public OperationResult GetById(int id)
{
try
{
// do stuff here
return OKResult( // some strongly-typed resource );
}
catch(SomeException ex)
{
return BadRequestResult(SomeErrorCode, ex.Message);
}
}
Then in the test client, it's pretty easy to just check the HTTP status code. Obviously this doesn't help much with mocking. I'm not sure what the best solution is, in fact I've favorited this question in the hope that someone answers it better than I can - but this has worked pretty well for me so far.
The handler is just a class--ideally with minimal dependencies--so your unit tests can just test the isolated logic in the class.
If you want to test for status codes, I recommend (based on very little experience!) using OpenRasta self-hosting.
Here's a test (somewhat changed) that I wrote recently:
[TestMethod]
public void POST_with_inaccurate_contentLength_returns_405()
{
var resource = GetResource();
IRequest request = new InMemoryRequest
{
HttpMethod = "POST",
Uri = new Uri("http://localhost/Resource"),
};
request.Headers.ContentLength = 16; //wrong!
request.Entity.Stream.Write(resource.Content, 0, resource.Content.Length);
var response = _host.ProcessRequest(request);
Assert.AreEqual(405, response.StatusCode);
}
I should add that the host is set up in the TestInitialize method as such:
_host = new InMemoryHost(new Configuration());
_host.Resolver.AddDependencyInstance(typeof(IFileResourceRepository), _repository, DependencyLifetime.Singleton);
...and is cleaned up in the TestCleanup method.
Related
I'm currently working on many .NET Core API projects and encountered a future possible regression.
How do you guys prevent this situation ?
Here's my architecture :
API project
BusinessLayer
API.UnitTests (references 2))
API.IntegrationTests (references 1 #for the casts))
An integration test example :
[Fact]
public async Task TestGetAll()
{
// Arrange
var query = "api/v1/xxx/getall";
// Act
var response = await _AuthorizedClient.GetAsync(query);
// Assert
Assert.True(response.IsSuccessStatusCode);
var results = JsonConvert
.DeserializeObject<List<MyResult>>(await response.Content.ReadAsStringAsync());
Assert.True(results.Any());
//Assert.AnythingOn(results);
}
Considering the next version and/or my [colleague] maintenance; with my deserializing cast, an update of the MyResult object might be hidden and create a production regression.
I've tried to do my integration test with the dynamic keyword and without casting but it take my much effort.
How do you deal with this situation ?
Are there any best practices ?
[Edit] After some search, I've found this article Differential Regression Testing for REST APIs which looks quite interesting
In my experience, dynamic is not a good practice because it will never fail on build but will fail on execution.
I think you should use something like this :
public static T DeserializeObject<T>(string value)
{
T result = default(T);
try {
result = JsonConvert.DeserializeObject<T>(value);
}
return result;
}
I have a method hello(HttpServletRequest request) that needs to be unit tested. In this method, I do something like this Cookie cookie = WebUtils.getCookie(request, cookie_name). So basically, I extract the cookie here and do my stuff. This is how my test class looks like:
#Test
public void testHello() {
Cookie cookie = new Cookie(cookie_name, "");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
Mockito.when(WebUtils.getCookie(request, cookie_name)).thenReturn(cookie);
// call the hello(request) and do assert
}
So whenever I try to mock and return this cookie, I end up with something like this in my stack trace.
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Cookie cannot be returned by getCookies()
getCookies() should return Cookie[]
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Inside WebUtils.getCookie(), it basically does request.getCookies() and iterates the array to get the correct one. This WebUtils comes from Spring Web. As you can see I have returned some value for that as well. Still getting this error. Has anyone faced this issue? How can I workaround this?
Following up on #Ajinkya comment, I think this is what he wanted to express:
The getCookie method might looks something like this (I just used some version of it, so there might have been some changes in the version you are using)
public static Cookie getCookie(HttpServletRequest request, String name) {
Assert.notNull(request, "Request must not be null");
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
Since you mocked your request you can control what getCookies() is returning.
To make this method working (without mocking it), you just would need to return a mock instead of a real Cookie from getCookies().
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn(cookie_name);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
Changing it to this and the static method can do its work as usual. You wouldn't need bother mocking it.
TL;DR;
"I like how my generated AutoRest client deserializes my main entities when dealing with the 200 scenarios.. but, MUST I manually parse the 400 scenarios?", said the lazy programmer
DETAILS:
So, I have an API, (Web API 2), and I do all the standard stuff.. using POCO's that implement IValidatable in addition to property-level validation using System.Data.DataAnnotations my Web API returns 400 errors like this (just an example):
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
And, where appropriate I use SwaggerResponse attributes, and my swagger.json is documented thus so that my generated client knows that a 400 is a viable response.
Now, my unit tests which directly instantiate the api controllers, I purposely try to test for invalid model state.. I can take the IHttpActionResult response from the controller invocation, and cast it to InvalidModelStateResult and iterate over the ModelState dictionary.
But, I find writing something similar for my 'production HTTP calls' with an actual HTTP client -- not as straightforward.
So, getting closer to the heart of my question:
Is there a preferred method for deserializing the InvalidModelStateResult?
So, when interacting with my API with actual http calls.. via the Microsoft.Rest.ServiceClient the JSON that I get back is in a slightly different shape..
Example MVC controller code interacting with my API:
HttpOperationResponse resp = await client.SpecialLocations.PatchByIdWithHttpMessagesAsync(id, locationType, "return=representation");
if (!resp.Response.IsSuccessStatusCode)
{
//The JSON returned here is not really in the form of an InvalidModelStateResult
ViewBag.Error = await resp.Response.Content.ReadAsStringAsync();
return View(locationType);
}
So, for now, I'm using Newtonsoft's JObject to parse ModelState returned from my WebAPI (again - it's not really named as such once retrieved via http request) and now pushing it into my MVC controller's ModelState.
This is my answer for now. But will consider others that have any merit. It just seems like a weird thing to have to do.
HttpOperationResponse resp = await client.SpecialLocations.PatchByIdWithHttpMessagesAsync(id, locationType, "return=representation");
if (resp.Response.StatusCode == HttpStatusCode.BadRequest)
{
string jsonErrStr = await resp.Response.Content.ReadAsStringAsync();
JObject err = JObject.Parse(jsonErrStr);
string[] valPair = ((string)err["error"]["innererror"]["message"]).Split(":".ToCharArray());
//now push into MVC controller's modelstate, so jQuery validation can show it
this.ModelState.AddModelError(valPair[0].Trim(),valPair[1].Trim());
return View(locationType);
}
I have just employed in a company, this company have a web site, i see some code like this:
public TicketReader()
{
HttpContext currentReq = HttpContext.Current;
try
{
Ticket = ((FormsIdentity)currentReq.User.Identity).Ticket;
}
catch
{
Ticket = null;
}
}
what are these codes mean?
TicketReader is a method that saves the information involving the visitor's individual HTTP request in a variable called currentReq. That variable will be used to create a Ticket-object. If it fails the Ticket-object is set to be nothing, which will probably be checked later on.
More information on HttpContext class by MSDN.
the short answer is it looks at the current http request and sets a ticket to the user, if that throws an error it sets the ticket to null(instead of the error type the command probably returns)
I would learn about httprequests if I were you and it will start making sense
what it basically does it break hierarchy intentionally(useful yet dangerous if you don't understand what you are doing)
While trying to write some unit tests with Moq and MVVM Light's messenger class I've encountered an issue. The issue is how can you Mock<IMessenger>(); and verify that a message was received and the action processed?
What is the correct way write the test if using IMessenger? I've seen plenty of examples using Messenger.Default,
and having Messenger.Reset() in the TestInitialize method. I used IMessenger believing it would help with test-ability.
Using Moq to verify that a message is sent works as I would expect.
[TestMethod]
public void LoadData_SendsUpdateStatusEvents()
{
//Arrange
_mockMessenger.Setup(x => x.Send(It.IsAny<string>(),
It.IsAny<UpdateStatusEvent>()));
//Act
//Assert
_mockMessenger.Verify(x => x.Send(It.IsAny<string>(),
It.IsAny<UpdateStatusEvent>()), Times.Exactly(2));
}
However, if I have this registration in my constructor..
_messenger.Register<IUnitsManager>(this, OnUpdatedUnitsEvent);
And I write a unit test to check that OnUpdatedUnitsEvent runs...
[TestMethod]
public void OnUpdatedUnitsEvent_UpdateUserUnitValueOfAllMaterials()
{
//Arrange
_mockUnits.Object.SetUnitsToMetric();
_mockMessenger.Object.Send(_mockUnits.Object);
//Act
var currentItem = _materialMasterVm.MaterialModels.CurrentItem as MaterialDetailViewModel;
//Assert
Assert.AreEqual(DensitySolidSymbols.KgCm3, currentItem.Density.UserUnitType);
Assert.AreEqual(PressureSymbols.KPa, currentItem.YieldStress);
Assert.AreEqual(PressureSymbols.KPa, currentItem.YoungsModulus);
}
What is the recommended approach to get this to work using when using IMessenger and Moq?
Here's what I would do:
// This is a field in your test fixture
Action<IUnitsManager> _callback;
...
// In your test setup, save the delegate that is registered with the message type
mockMessenger.Setup(x => x.Register(It.IsAny<object>(), It.IsAny<Action<IUnitsManager>>()))
.Callback<object, Action<IUnitsManager>>((o, a) => _callback = a);
...
// When you want to send the message, invoke the callback
_callback(_mockUnits.Object);
However, I want to add that when sending messages in tests using the IMessenger, I do not mock it. The above is a little too much hassle to setup, and besides, this is exactly what the Messenger concrete does anyways. To put it another way, I'm either putting my faith in Moq's Setup/Callback mechanism or in the MVVM Light Messenger's Register/Send mechanism. I choose the latter because I don't need to do any extra setup in my tests to make it work.
So, when I need to test that my SUT registers for and handles messages properly, I assume the IMessenger works as expected and just use a concrete instance, i.e.:
// Create a new messenger every test
IMessenger mockMessenger = new Messenger();
// Send the message
mockMessenger.Send<IUnitsManager>(_mockUnits.Object);