ServiceStack:如何对提供文件的服务进行单元测试

ServiceStack: How to unit test a service that serves files

我有一个为 Excel 文件提供服务的 Web 服务

public class ReportService : Service
{
    public IReportRepository Repository {get; set;}

    public object Get(GetInvoiceReport request)
    {
        var invoices = Repository.GetInvoices();

        ExcelReport report = new ExcelReport();
        byte[] bytes = report.Generate(invoices);

        return new FileResult(bytes);
    }
}

我将从服务返回的对象设置为

public class FileResult : IHasOptions, IStreamWriter, IDisposable
{
    private readonly Stream _responseStream;
    public IDictionary<string, string> Options { get; private set; }

    public BinaryFileResult(byte[] data)
    {
        _responseStream = new MemoryStream(data);

        Options = new Dictionary<string, string>
        {
            {"Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {"Content-Disposition", "attachment; filename=\"InvoiceFile.xlsx\";"}
        };
    }

    public void WriteTo(Stream responseStream)
    {
        if (_responseStream == null)
            return;

        using (_responseStream)
        {
            _responseStream.WriteTo(responseStream);
            responseStream.Flush();
        }
    }

    public void Dispose()
    {
        _responseStream.Close();
        _responseStream.Dispose();
    }
}

现在,通过浏览器测试时,web 服务工作正常;但在单元测试中测试时会给出错误消息。以下是错误信息:

System.Runtime.Serialization.SerializationException : Type definitions should start with a '{', expecting serialized type 'FileResult', got string starting with: PK\u0003\u0004\u0014\u0000\u0008\u0000\u0008\u0000�\u000b5K���%\u0001\u0000\u0000�\u0003\u0000\u0000\u0013\u0000\u0000\u0000[Content_Types].xml�� at ServiceStack.Text.Common.DeserializeTypeRefJson.StringToType(TypeConfig typeConfig, StringSegment strType, EmptyCtorDelegate ctorFn, Dictionary2 typeAccessorMap) at ServiceStack.Text.Common.DeserializeType1.<>c__DisplayClass2_0.b__1(StringSegment value) at ServiceStack.Text.Json.JsonReader1.Parse(StringSegment value) at ServiceStack.Text.Json.JsonReader1.Parse(String value)
at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value) at ServiceStack.Text.JsonSerializer.DeserializeFromStream[T](Stream stream) at ServiceStack.ServiceClientBase.GetResponse[TResponse](WebResponse webResponse) at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)

下面是我用来测试webservice的单元测试:

[Test]
public void TestInvoiceReport()
{
    var client = new JsonServiceClient("http://localhost/report/");

    var authResponse = client.Send(new Authenticate
                {
                    provider = CredentialsAuthProvider.Name,
                    UserName = "[User Name]",
                    Password = "[Password]"
                }); 

    var requestDTO = new GetInvoiceReport();

    var ret = client.Get<FileResult>(requestDTO);

    Assert.IsTrue(ret != null);
}

编辑: 我包括了我的请求 DTO class:

的定义
[Route("/invoices", "GET")]
public class GetInvoiceReport: IReturn<FileResult>
{

}

感谢任何帮助。

注意:如果您发出 HTTP 请求而不是在代码中调用服务,则它是 Integration Test 而不是单元测试。

您还没有提供您的 GetInvoiceReport 请求 DTO 定义,但是如果您返回任何不是序列化 DTO 的东西,应该指定它的 IReturn<T> 接口,例如:

public class GetInvoiceReport : IReturn<byte[]> { ... }

然后您就可以通过以下方式下载原始字节:

byte[] response = client.Get(new GetInvoiceReport());

您可以使用服务客户端请求过滤器来检查 HTTP 响应Headers。

我还建议查看 ServiceStack 的 .NET 服务客户端文档,其中包含有关 downloading raw Responses 的大量信息。