简体   繁体   中英

Getting content from HttpResponseMessage for testing using c# dynamic keyword

In one of the actions, I do something like this

public HttpResponseMessage Post([FromBody] Foo foo)
{
    .....
    .....

    var response = 
          Request.CreateResponse(HttpStatusCode.Accepted, new { Token = "SOME_STRING_TOKEN"});
    return response;
}

and more methods like that return an anonymous type instance and it works well.

Now, I'm writing tests for it. I have

HttpResponseMessage response = _myController.Post(dummyFoo);

HttpResponseMessage has a property called Content and has a ReadAsAsync<T>() .

I know that if there was a concrete specific type, I can do

Bar bar = response.Content.ReadAsAsync<Bar>();

but how do I access the anonymous type that's being returned? Is it possible?

I was hoping to do the following:

dynamic responseContent = response.Content.ReadAsAsync<object>();
string returnedToken = responseContent.Token;

but I got the error that instance of type object does not have the property Token. This happens even though the debugger shows responseContent with one property Token. I understand why that's happening, but I want to know if there is a way to access the Property.

在此输入图像描述

Thanks

.ReadAsAsync<T> is an asynchronous method, meaning that it doesn't return the whole deserialized object but a Task<T> to handle the continuation of the whole asynchronous task.

You've two options:

1. Async pattern.

Use the async keyword in your enclousing method (for example: public async void A() ) and do the asynchronous call this way:

dynamic responseContent = await response.Content.ReadAsAsync<object>();
string returnedToken = responseContent.Token;

2. Regular task API

Or just use the Task API:

response.Content.ReadAsAsync<object>().ContinueWith(task => {
   // The Task.Result property holds the whole deserialized object
   string returnedToken = ((dynamic)task.Result).Token;
});

It's up to you!

Update

Before you posted the whole screenshot, no one could know that you're calling task.Wait in order to wait for the async result. But I'm going to maintain my answer because it may help further visitors :)

As I suggested in a comment to my own answer, you should try deserializing to ExpandoObject . ASP.NET WebAPI uses JSON.NET as its underlying JSON serializer. That is, it can handle anonymous JavaScript object deserialization to expando objects.

You can also use the similar following code to test the HttpResponseMessage using Unit Testing.

This worked for me.

Hope this will help you

[TestClass]
    public class UnitTest
    {
        [TestMethod]
        public void Post_Test()
        {
           //Arrange
           var contoller = new PostController();  //the contoller which you want to test
           controller.Request = new HttpRequestMessage();
           controller.Configuration = new HttpConfiguration();

           // Act
           var response = controller.Post(new Number { PhNumber = 9866190822 });
           // Number is the Model name and PhNumber is the Model Property for which you want to write the unit test

           //Assert
           var request = response.StatusCode;
           Assert.AreEqual("Accepted", request.ToString());

        }
    }

Similarly according to the need change the HttpResponseMessage in the Assert.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM