Unit Testing null reference exception for controll

2019-07-09 01:12发布

I'm trying to test controller and I want to change it's context so I can post message with file in request My code looks like that:

System.Drawing.Image image = System.Drawing.Image.FromFile("..\\..\\Images\\UploadFileTest.jpg");

var converter = new System.Drawing.ImageConverter();
byte[] byteContent = (byte[]) converter.ConvertTo(image,typeof(byte[]));
var content = new ByteArrayContent(byteContent);
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext()
{
    Request = new HttpRequestMessage() { Content = new MultipartContent() { content } }
};
var controller = new ActionsController();
controller.ControllerContext = controllerContext;
string fileUrl = controller.UploadFile();

However I get NullReferenceExcetion in my controller on line:

var request = HttpContext.Current.Request;

3条回答
别忘想泡老子
2楼-- · 2019-07-09 01:45

I am not sure if you using this code in Asp.net Mvc, but I will assume you are. The best way I think of doing this is to write an extension method on the Request object and then in that method do your magic like this,

        public static class RequestMessageExtensions
    {
        internal static byte[] GetContent(this HttpRequestMessage request)
        {
            System.Drawing.Image image = System.Drawing.Image.FromFile("..\\..\\Images\\UploadFileTest.jpg");

        var converter = new System.Drawing.ImageConverter();
        byte[] byteContent = (byte[]) converter.ConvertTo(image,typeof(byte[]));
        var content = new ByteArrayContent(byteContent);
        content.Headers.Add("Content-Disposition", "form-data");

return content;
        }
  }

You can then call the Content on the request object and access you data.

I hope this helps

Thanks

查看更多
再贱就再见
3楼-- · 2019-07-09 01:58

In production, the IIS Server which host your application populates HttpContext.Current for each request.(specific context)

In your UT nothing was populate HttpContext.Current to an instance, this is the problem.

You have to initialize HttpContext.Current:

HttpContext.Current = new HttpContext(new HttpRequest("", "http://blabla.com", ""),
                                      new HttpResponse(new StringWriter()));

One more thing(just in case you are going to fake HttpContext); HttpContext is a sealed class, you won't be able to fake it using proxy tools like Rhino-Mocks / Moq. You'll have to use code weaving tools like MsFakes / TypeMock Isolator...

查看更多
劳资没心,怎么记你
4楼-- · 2019-07-09 02:04

You can fake HttpContext with Typemock Isolator:

var fake = Isolate.Fake.AllInstances<HttpContext>();
Isolate.Fake.StaticMethods<HttpContext>();

These lines make so-called recursive fake, which means that calling any members and their members etc doesn't cause an exception, it'll return default value or another recursive fake. Also, it solves the singleton problem that usually arises with faking HttpContext.

If you want to set specific values, just use Isolate.WhenCalled(..).Return() methods. For example:

Isolate.WhenCalled(() => HttpContext.Current.Request).WillReturn(new HttpRequest("", "http://smth.com", ""));

Hope it hepls!

查看更多
登录 后发表回答