2

我正在尝试测试从 Request.InputStream 读取 JSON 并输出动态的控制器操作。我不明白 Mock Request.InputStream 类型应该是什么。我已经尝试将它作为 MemoryStream 并传递给它一个字节数组,但它无法读取它。

到目前为止,我的模拟看起来像这样:

var str = "{ MediaItem: null, ParentId: 2897, Post: null, PostContent: hello }";
byte[] bytes = new byte[str.Length * sizeof(char)];
Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
var stream = new MemoryStream(bytes);

var request = new Mock<HttpRequestBase>();
request.SetupGet(x => x.InputStream).Returns(stream);
request.Setup(x => x.InputStream).Returns(stream);
request.Setup(x => x.Url).Returns(new Uri("http://localhost:35199/api/comment/create"));

var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);

CommentController controller = new CommentController(pr, ur, er, apr, ar);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);

ActionResult expected = null;
ActionResult actual = controller.Create();

JSON 阅读器这样做:

public static dynamic SqueezeJson(HttpRequestBase Request)
{        
    var bodyText = "";
    using (var stream = Request.InputStream)
    {
        stream.Seek(0, SeekOrigin.Begin);
        using (var reader = new StreamReader(stream))
            bodyText = reader.ReadToEnd();
    }
    if (string.IsNullOrEmpty(bodyText)) return null;

    return JsonConvert.DeserializeObject<ExpandoObject>(bodyText, new ExpandoObjectConverter());
}

这会引发此错误:

解析属性名称后出现无效字符。预期的':'但得到:a。路径 '',第 1 行,位置 6。

编辑:我应该提到我没有重构控制器代码的自由。

4

2 回答 2

1

刚刚将您的 Json 字符串粘贴到解析器中,但它失败了。您是否尝试将其更改为有效的 Json 表示?

{ "MediaItem": "null", "ParentId": "2897", "Post": "null", "PostContent": "hello" }

针对您的场景进行了更新:

var str = "{ \"MediaItem\": \"null\",\"ParentId\": \"2897\", \"Post\": \"null\", \"PostContent\": \"hello\" }";

高温高压

于 2013-06-13T08:08:39.710 回答
-1

看起来你的控制器做了太多的工作。尝试将json阅读器抽象到另一个类中,并将其注入控制器中。这样,您将有 2 个独立的测试 - 一个用于阅读器本身,另一个用于控制器,它只是调用阅读器,而实际上不必考虑阅读器的工作方式。

像这样的东西(伪代码):

public interface IJsonReader
{
   dynamic SqueezeJson(Stream stream);
}

public class JsonReader : IJsonReader
{
   //implement SqeezeJson method
}

public class MyController
{
   private readonly IJsonReader _jsonReader;
   public MyController(IJsonReader jsonReader)
   {
      _jsonReader = jsonReader;
   }

   public ActionResult Create()
   {
       var data = _jsonReader.SqeezeJson(Context.Request.InputStream);
       //... do wahtever needed
   }
}

// ... and the tests

[Test]
public void SqueezeJsonTest()
{
   //test that the reader works as expected
}

public void ControllerTest()
{
   //arrange
   var requestStream = Mock.Of<Stream>();
   var request = Mock.Of<HttpRequestBase>( r => 
       r.InputStream == requestStream &&
       r.Url == "http://whatever");
   var context = Mock.Of<HttpRequestBase>(c=>c.Request == request);

   dynamic sqeezedData = new ExpandoObject(); // populate with the expected data from reader
   var mockReader = new Mock<IJsonReader>();
   mockReader.Setup(r=>r.SqeezeJson(requestStream)).Returns(sqeezedData); 

   var controller = new MyController();
   controller.Context = context;

   //act
   var result = controller.Create();

   //assert
   //whatever is needed to verify that the controller processed the sueezed data
}
于 2013-06-12T18:34:10.470 回答