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.DeserializeType
1.<>c__DisplayClass2_0.b__1(StringSegment value) at ServiceStack.Text.Json.JsonReader1.Parse(StringSegment
value) at ServiceStack.Text.Json.JsonReader
1.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 的大量信息。
我有一个为 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, Dictionary
2 typeAccessorMap) at ServiceStack.Text.Common.DeserializeType
1.<>c__DisplayClass2_0.b__1(StringSegment value) at ServiceStack.Text.Json.JsonReader1.Parse(StringSegment value) at ServiceStack.Text.Json.JsonReader
1.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 的大量信息。