2

I could really use some help understanding why this unit test is failing. I suspect it's due to the way I'm handling the streams. I have a number of other tests that successfully use this self-hosting server setup, but they all read services that return primitives like strings.

Here's the test in question:

using System.Net.Http;
using System.Threading;
using System.Web.Http.SelfHost;
using AttributeRouting.Web.Http.SelfHost;
using NUnit.Framework;

[TestFixture]
public class StreamControllerTests 
{
    [Test]
    public void Can_get_simple_streaming_service_to_respond()
    {
        using (var config = new HttpSelfHostConfiguration("http://in-memory"))
        {
            config.Routes.MapHttpAttributeRoutes();
            using (var server = new HttpSelfHostServer(config))
            {
                // I get the same behavior if I use HttpClient
                using (var client = new HttpMessageInvoker(server))
                {
                    using (var request = new HttpRequestMessage(HttpMethod.Get, "http://in-memory/stream/notepad"))
                    {
                        using (HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result)
                        {
                            Assert.IsNotNull(response.Content);
                            // FAILS, content length is 0
                            Assert.Greater(response.Content.Headers.ContentLength, 0); 
                        }
                    }
                }
            }
        }

And here is the controller that feeds the test:

using System;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AttributeRouting.Web.Mvc;
using MyUnitTests.Properties;

[GET("stream/notepad")]
public HttpResponseMessage StreamAnImageFromResources()
{
    var imageStream = new MemoryStream(); // closed when stream content is read
    Resources.a_jpeg_in_resources.Save(imageStream, ImageFormat.Jpeg);
    try
    {                               
        HttpResponseMessage response = Request.CreateResponse();
        // at this point, imageStream contains about 120K bytes
        response.Content = new StreamContent(imageStream); 
        return response;            
    }
    catch (Exception e)
    {
        return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, e);
    }
}
neontapir
  • 4,698
  • 3
  • 37
  • 52

1 Answers1

2

I don't see anything really wrong but your test is more complicated than it needs to be.

Try this,

[Test]
public void Can_get_simple_streaming_service_to_respond2()
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpAttributeRoutes();
    var server = new HttpServer(config);

    var client = new HttpClient(server);

    var request = new HttpRequestMessage(HttpMethod.Get, "http://in-memory/stream/notepad");

    HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result;

    Assert.IsNotNull(response.Content);
    // FAILS, content length is 0
    Assert.Greater(response.Content.Headers.ContentLength, 0);
}

EDIT: In the comments, Darrel gave me the true answer, which I'm moving to the answer body for visibility:

Check the position of your image stream after doing Save. You need to reset it back to 0 before passing to StreamContent. Also, you might want to consider doing GetManifestResourceStream instead, it will save copying the bytes into managed memory.

neontapir
  • 4,698
  • 3
  • 37
  • 52
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • Agreed, this is a simpler test, but unfortunately it still fails the same way. I'm using DI in my solution, and it took a while to get it working. I ended up created a derived class called `NinjectSelfHostConfiguration` to handle creation of the kernel and bindings. I will have to experiment to see if I can get `HttpServer` working in that scenario -- it would be lighter weight than self-hosting. Thanks! – neontapir Aug 30 '13 at 14:11
  • @neontapir Check the position of your imagestream after doing Save. You need to reset it back to 0 before passing to StreamContent. Also, you might want to consider doing GetManifestResourceStream instead, it will save copying the bytes into managed memory. – Darrel Miller Aug 30 '13 at 18:34
  • Resetting the stream position was the missing piece. (facepalm) Thank you! – neontapir Sep 03 '13 at 18:04
  • This helped me too (same mistake!) but that comment should be in the answer as it's the actual answer to the question – Ben Aaronson May 22 '15 at 13:08