3

我正在编写一些代码,将 C# 对象序列化为 JSON,通过网络发送并将 JSON 反序列化为 Python 对象。

反向操作也将完成,即将 Python 对象序列化为 JSON,通过网络发送并将 JSON 反序列化为 C# 对象。

在 C# 方面,我使用 ServiceStack JSON 库。在 Python 中,我使用的是内置的 json 库。如有必要,可以轻松更改 C# 库,而 Python 则要少得多。

// C#
var serializer = new JsonSerializer();
var json = serializer.SerializeToString(request);

// Python
// JsonCodec 继承自 JSONEncoder 并挂钩到 'default' 并且只是
// 返回 obj.__dict__ 其中 obj 是要序列化的对象
actualSerializedResponse = JsonCodec().encode(response)

我用 C# 编写了一个单元测试来验证 ServiceStack 序列化的 JSON 是否符合 Python 端的预期。在测试中,创建了一个 Foo 实例,填充了一些硬编码值,然后序列化。为了确保有效性,我将序列化的 JSON 与保存在文件中的一些 JSON 进行比较,其中文件的内容代表 Python 端的期望。

同样,在 Python 中有一个单元测试来验证内置 json 库的序列化 JSON 是否符合 C# 端的预期。同样,为了确保有效性,我将实际的序列化 JSON 与保存在文件中的一些 JSON 进行比较。

在这两种情况下,我将序列化的 JSON 与保存在文件中的一些 JSON 进行比较这一事实意味着,每次运行测试时,将属性序列化为 JSON 的顺序必须保持一致。

我的问题:

  • 在 C# 单元测试中,JSON 中属性的顺序似乎与在其实例被序列化的 C# 类中定义属性的顺序相匹配。这可以依靠吗?

  • 在 Python 单元测试中,属性的顺序是一致的,但是是任意的。这是有道理的,因为它依赖于dict并且 Python 字典是无序的。但这可以每次/哪里都可靠吗?

  • 有没有更好的方法来完成这一切?

提前谢谢了。

4

2 回答 2

1

关于 Python 方面:您可以向 JSON 解码器传递一个选项以使用“有序字典”(但需要 python 2.7):

来自http://docs.python.org/library/json.html#json.load

object_pairs_hook 是一个可选函数,将调用使用有序对列表解码的任何对象文字的结果。将使用 object_pairs_hook 的返回值而不是 dict。此功能可用于实现依赖于键值对解码顺序的自定义解码器(例如,collections.OrderedDict() 将记住插入顺序)。如果还定义了 object_hook,则 object_pairs_hook 优先。

于 2012-04-05T22:54:19.583 回答
1

你的前两个问题很容易解决。只要可以避免,就不应依赖未记录的、特定于实现的行为。我认为你可以避免在这里这样做。为了进一步充实这个答案,我将花一些时间来解决您的最后一个问题。

有没有更好的方法来完成这一切?

第一步是认识到您当前编写的不是单元测试

具体来说:

如果满足以下条件,则测试不是单元测试:

  • 它通过网络进行通信
  • 它涉及文件系统

你的测试正在做这两个。这并不是说您的测试没有任何价值,但重要的是要注意它们不是单元测试。这些测试工作的级别是集成测试。集成测试是:

软件测试的阶段,其中将各个软件模块组合在一起并作为一个组进行测试。它发生在单元测试之后和验证测试之前

我认为你的问题是你试图混合集成和单元测试的任务。

在编写单元测试时,您希望每个测试尽可能少地依赖组件,并尽可能具体地解决案例。在您的情况下,这意味着 C# 和 Python 中的测试,它们都不依赖于另一个的输出。在这两个程序中,让您的序列化代码在您需要它工作的最简单的情况下工作,并验证您是否获得了所需的 JSON 加载/转储。这可能意味着在您的单元测试代码中将 JSON 作为字符串手动编写(您希望您的测试足够小以至于这不会很痛苦)。

对于您的集成测试,您只想检查当您的不同部分相互交谈时没有发生任何故障。在这里,您不必担心序列化和读取是否正确,因为您已经在单元测试中涵盖了这一点。如果他们说得很好,那就太好了!

Then, if you run in to bugs, fix them and document them with an appropriate test case. In the end you should have lots of little unit tests and a few slightly bigger integration tests.

于 2012-04-05T22:54:42.210 回答