C# 用于安排单元测试的序列化对象图

C# 用于安排单元测试的序列化对象图,c#,unit-testing,testing,serialization,tdd,C#,Unit Testing,Testing,Serialization,Tdd,我有一个应用程序,其中问题域由高度相关的域对象表示。我已经将域拆分为几个聚合根对象,这有助于对模型施加顺序,但是为单元测试安排先决条件非常困难,因为创建这些聚合根的实例需要创建大量被引用的支持对象 我希望编写可重复的、独立的单元测试,以在不需要外部依赖项的情况下(理想情况下,不需要编写大量代码)运行应用程序 我想这是我的选择。有什么偏好或其他建议吗 编写构建脚本,设置项目数据库并将已知数据插入其中,然后根据这些脚本执行单元测试。这是我最不喜欢的选项,因为它引入了外部依赖关系(因此不是真正的单元测

我有一个应用程序,其中问题域由高度相关的域对象表示。我已经将域拆分为几个聚合根对象,这有助于对模型施加顺序,但是为单元测试安排先决条件非常困难,因为创建这些聚合根的实例需要创建大量被引用的支持对象

我希望编写可重复的、独立的单元测试,以在不需要外部依赖项的情况下(理想情况下,不需要编写大量代码)运行应用程序

我想这是我的选择。有什么偏好或其他建议吗

  • 编写构建脚本,设置项目数据库并将已知数据插入其中,然后根据这些脚本执行单元测试。这是我最不喜欢的选项,因为它引入了外部依赖关系(因此不是真正的单元测试)以及更多的潜在故障。它也不会隔离正在测试的业务功能,因为故障可能存在于数据访问代码中

  • 创建可重复使用的工厂,这些工厂创建具有已知状态的域对象,并针对这些对象运行单元测试。这将很好地工作,但意味着要编写大量样板代码,因此在模型更改时/如果模型更改,将有大量代码需要更改

  • (当前方法)将聚合根对象的二进制序列化创建到与测试项目签入的文件中。单元测试为它们的测试反序列化它们。这样做的缺点是,如果基础类型更改,反序列化将失败,并且必须重新创建所有序列化文件

  • 吸收它并编写一个自定义序列化程序,将图形序列化为XML文件,这些文件可以检入解决方案并在测试时反序列化。与2类似,这意味着要编写大量的前端样板代码,但维护更容易,因为如果模型发生更改,可以使用文本编辑器轻松编辑序列化状态

  • 你干得不错。域对象具有高度的引用性是主要问题。简化它

  • 谢谢

    编写构建脚本,设置项目数据库并将已知数据插入其中,然后根据这些脚本执行单元测试。这是我最不喜欢的选项,因为它引入了外部依赖关系(因此不是真正的单元测试)以及更多的潜在故障。它也不会隔离正在测试的业务功能,因为故障可能存在于数据访问代码中

    “集成而不是单元”是一个小问题(特别是与“测试或不测试”相比),我不担心这一点。这种方法还有其他更严重的问题:

    • 写剧本。您很可能会手工编写SQL,这需要很多规程,尤其是在模型复杂的情况下。打字错误是痛苦的,很难调试/检测问题,您也需要考虑IDE/工具
    • 当您的模型发生更改时,您将修复这些SQL脚本,这会引发相同的问题—打字错误、难以发现错误等等,以及缺少IDE支持
    总的来说,这种方法在可维护性方面成本很高

    创建可重复使用的工厂,这些工厂创建具有已知状态的域对象,并针对这些对象运行单元测试。这将很好地工作,但意味着要编写大量样板代码,因此在模型更改时/如果模型更改,将有大量代码需要更改

    如果采用适当的方法,您应该研究使此过程更容易的库(提示:,)

    (当前方法)将聚合根对象的二进制序列化创建到与测试项目签入的文件中。单元测试为它们的测试反序列化它们。这样做的缺点是,如果基础类型更改,反序列化将失败,并且必须重新创建所有序列化文件

    与构建脚本的问题相同-更改将非常昂贵

    吸收它并编写一个自定义序列化程序,将图形序列化为XML文件,这些文件可以检入解决方案并在测试时反序列化。与2类似,这意味着要编写大量的前端样板代码,但维护更容易,因为如果模型发生更改,可以使用文本编辑器轻松编辑序列化状态

    <>这实质上是与第二个相同的解决方案,但是XML是中间的人。为什么要添加额外的层

    你干得不错。域对象具有高度的引用性是主要问题。简化它

    不太可能。就其性质而言,域对象往往是复杂的

    结论
    对于这样的问题,没有快速而肮脏的解决办法。复杂域意味着在某个点上必须做一些额外的工作。基于序列化的解决方案(1、3、4),即使有些现在看起来很简单,也只会将所说的额外工作推迟到引入更改时。几乎在所有情况下,我都会选择更灵活的随时准备更改的(只有第二种解决方案可以提供,如果操作得当)。

    您所说的问题是,数据分散在域对象图中:

    如果你想计算发票的价格,你需要物品价格、税务信息、特定于客户的结算、特定于交货期的运输成本等等

    处理这种复杂性的一种策略是将逻辑从实际计算中分离出来,以获得这些细节值

    该计算是一种内部方法,具有许多参数,对其他域对象的依赖性最小。这很容易测试,因为它不再依赖于对象图


    另一种策略是将复杂的计算从域移动到依赖于其他服务接口的独立服务层。为了测试这些服务接口,可以用mock代替

    指给我看那些图书馆我想你