1

我正在为从 Request.InputStream 读取 POST 正文的 WebApi 控制器编写单元测试。我需要设置HttpContext.Current.Request.InputStream的inputstream属性,或者设置inputstream的内容。到目前为止,这是我的单元测试代码,但它不断抛出异常:

var originalStream = HttpContext.Current.Request.InputStream;
Stream newStream = new MemoryStream(ASCIIEncoding.Default.GetBytes("Test String"));

var propInfo = originalStream.GetType().GetProperty("CanWrite");
propInfo.SetValue(originalStream, true);

newStream.CopyTo(originalStream);

propInfo.SetValue(originalStream, false);

我在 SetValue 行上收到以下异常:

ArgumentException: Property set method not found

我对这一切都错了吗?我的控制器读取输入流并将其反序列化为 JSON,因此我需要能够将数据插入到该流中。我只是不知道该怎么做。非常感谢。

4

2 回答 2

2

public abstract bool CanWrite { get; }. 该属性没有设置器..因此您的错误。

在您的示例中,originalStream将是Stream. 将其包装在另一个流中以供您测试。您不是在测试HttpRequest.InputStream,而是在测试反序列化 ...

var originalStream = new StreamReader(HttpContext.Current.Request.InputStream);
var content = originalStream.ReadToEnd();

.. ETC。

您甚至可以考虑完全跳过使用请求输入,因为您并没有真正测试它。

编辑:

再扩大一点。您应该将其移出控制器操作.. 执行以下操作:

public class YourController : Controller {
    private readonly IStreamWrapper _streamWrapper;

    public YourController(IStreamWrapper wrapper) {
        _streamWrapper = wrapper;
    }

    public ActionResult MethodYouAreTesting() {
        var result = _streamWrapper.Process(HttpRequest.InputStream);
    }
}

public class Tests {
    public void YourTestMethod() {
        var controller = new YourController(new FakeStreamWrapper()); // mock perhaps?
        // Asserts here for the controller action
    }

    public void YourWrapperTester() {
        var wrapper = new RealStreamWrapper();
        // test Process method here..
    }
}

然后您可以单独测试流读取和反序列化。

这有意义还是我让它变得更复杂了?:/

于 2013-02-06T23:46:13.447 回答
0

InputStream 是一个只读流。

有几种方法。从最简单的开始:

创建 StreamReader 的实例并在 InputStream 上调用 ReadToEnd() 以获取正在发送的数据。

获得内容后,您可以在进行 JSON 转换之前根据需要进行修改。

同样,这是做你想做的最简单、最不优雅的方法,但它应该可以工作。

于 2013-02-06T23:46:45.840 回答