使用自定义序列化/反序列化对servicestack服务进行单元测试
本文关键字:服务 servicestack 单元测试 反序列化 自定义 序列化 | 更新日期: 2023-09-27 18:27:44
我在测试具有自己的反序列化机制的Web服务时遇到问题。
TaskService
:正在使用的示例Task
类
public class Task
{
public string TaskName { get; set; }
public string AuxData { get; set; }
public static void RegisterCustomSerialization(IAppHost appHost)
{
appHost.ContentTypeFilters.Register("application/xml", SerializeTaskToStream, DeserializeTaskFromStream);
}
public static void SerializeTaskToStream(IRequestContext requestContext, object response, Stream stream)
{
var tasks = response as List<Task>;
if (tasks != null)
{
using (var sw = new StreamWriter(stream))
{
if (tasks.Count == 0)
{
sw.WriteLine("<Tasks/>");
return;
}
sw.WriteLine("<Tasks>");
foreach (Task task in tasks)
{
if (task != null)
{
sw.WriteLine(" <Task type='"new serializer'">");
sw.Write(" <TaskName>");
sw.Write(task.TaskName);
sw.WriteLine("</TaskName>");
sw.Write(" <AuxData>");
sw.Write(task.AuxData);
sw.WriteLine("</AuxData>");
sw.WriteLine(" </Task>");
}
}
sw.WriteLine("</Tasks>");
}
}
else
{
var task = response as Task;
using (var sw = new StreamWriter(stream))
{
if (task != null)
{
sw.WriteLine(" <Task type='"new serializer'">");
sw.Write(" <TaskName>");
sw.Write(task.TaskName);
sw.WriteLine("</TaskName>");
sw.Write(" <AuxData>");
sw.Write(task.AuxData);
sw.WriteLine("</AuxData>");
sw.WriteLine(" </Task>");
}
}
}
}
public static object DeserializeTaskFromStream(Type type, Stream stream)
{
if (stream == null || stream.Length == 0)
return null; // should throw exception?
XDocument xdoc = XDocument.Load(stream);
XElement auxData = xdoc.Root.Element("AuxData");
return new Task() { AuxData = auxData.Value };
}
public override bool Equals(object obj)
{
Task task = obj as Task;
if (task == null)
return false;
return TaskName.Equals(task.TaskName);
}
public override int GetHashCode()
{
return TaskName.GetHashCode();
}
}
我的序列化/反序列化代码基于:http://www.servicestack.net/ServiceStack.Northwind/vcard-format.htm和https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/ServiceStack.Northwind/ServiceStack.Northwind.ServiceInterface/VCardFormat.cs
我的基本测试类如下:
public class SimpleRestTestBase : AppHostBase
{
public SimpleRestTestBase() : base( "SimpleRestTestBase", typeof(TaskService).Assembly)
{
Instance = null;
Init();
}
public override void Configure(Funq.Container container)
{
SetConfig(new EndpointHostConfig
{
DefaultContentType = ContentType.Xml
}
);
Task.RegisterCustomSerialization(this);
Routes
.Add<Task>("/tasks/{TaskName}")
.Add<List<Task>>("/tasks");
container.Register(new List<Task>());
}
}
失败的单元测试:
[TestFixture]
public class SimpleTest : SimpleRestTestBase
{
[Test]
public void TestMetodRequiringServer()
{
var client = (IRestClient)new XmlServiceClient("http://localhost:53967");
var data = client.Get<List<Task>>("/api/tasks");
}
}
当使用UnUnit测试运行程序时,我得到的异常是:
Testing.SimpleTest.TestMetodRequiringServer:
System.Runtime.Serialization.SerializationException : Error in line 1 position 9. Expecting element 'ArrayOfTask' from namespace 'http://schemas.datacontract.org/2004/07/ServiceStackMVC'.. Encountered 'Element' with name 'Tasks', namespace ''.
如何将有关自定义序列化/反序列化代码的信息传递给XmlServiceClient
?
您正在用一个强耦合的自定义版本覆盖通用XML序列化格式(application/XML),该版本只能处理1个web服务输出-这很少是您想要的,因为它会阻止(即中断)所有其他服务返回XML。如果您想返回自定义XML,只需通过返回XML字符串来限制需要它的服务即可。
不能更改XmlServiceClient的实现,因为它与ServiceStack使用的XML序列化/去序列化强耦合。您应该使用原始HTTP客户端来发送所需的确切XML负载。下面是一个使用.NET的web请求发送原始XML的示例:https://stackoverflow.com/a/8046734/85785
由于您要返回并发送自定义XML,您可能还需要覆盖web服务的自定义请求绑定器,以便有机会按您的意愿反序列化请求。
有关如何做到这一点的一些示例,请参阅下面的wiki页面:
https://github.com/ServiceStack/ServiceStack/wiki/Serialization-deserialization
注意:返回自定义XML并不理想,因为它忽略了ServiceStack强类型、智能和固执己见的许多优点。