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

标签 c# unit-testing testing serialization tdd

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

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

我认为这些是我的选择。有什么偏好或其他建议吗?

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

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

  3. (当前方法)将我的聚合根对象的二进制序列化创建到与测试项目一起 checkin 的文件中。单元测试反序列化它们以进行测试。这样做的缺点是,如果基础类型发生变化,反序列化将失败,并且必须重新创建所有序列化文件。

  4. 接受它并编写一个自定义序列化程序,将图形序列化为 XML 文件,这些文件可以 checkin 解决方案并在测试时反序列化。与 2 一样,这意味着要编写大量前期样板代码,但维护起来更容易,因为如果模型发生变化,可以使用文本编辑器轻松编辑序列化状态。

  5. 你做得很好。您的域对象具有如此高的引用性这一事实是主要问题。简化它。

谢谢!

最佳答案

Write build scripts that setup the project database and INSERT known data into it, against which unit tests are executed. This is my least favorite option as it introduces an external dependency (and therefore isn't a true unit test) as well as many more potential failures. It also doesn't isolate the business function being tested because the fault could lie within the data access code.

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

  • 编写脚本。您很可能最终会手动编写 SQL 代码,这需要大量的纪律,尤其是当模型很复杂时。错别字很痛苦,很难调试/检测问题,您还需要考虑 IDE/工具。
  • 当您的模型发生变化时,您将修复那些 SQL 脚本,这会引发同样的问题 - 拼写错误、难以发现错误等等,缺乏 IDE 支持。

总的来说,这种方法在可维护性方面代价高昂

Create re-usable factories that create domain objects with a known state, against which unit tests are run. This will work well, but means lots of boilerplate code to be written, and therefore lots to change when/if the model changes.

体面的方法,你应该研究使这个过程更容易的库(提示:AutoFixtureNBuilder)。

(Current method) Create binary serializations of my aggregate root objects into files that are checked in with the test project. The unit tests deserialize them for their tests. The downside to this is that if the underlying type changes deserialization will fail and all the serialized files have to be re-created.

与构建脚本一样的问题 - 更改将是昂贵的。

Suck it up and write a custom serializer that serializes the graphs to XML files that can be checked in to the solution and deserialized at test time. Like 2, this means alot of up-front boilerplate code to be written, but maintenance is easier as the serialized state can be edited easily with a text editor if the model changes.

这与您的第二个解决方案本质上是相同的,但在中间使用了 XML。为什么要添加额外的层?

UR DOIN IT RONG. The fact that your domain objects are so highly referential is the main problem. Simplify it.

不太可能。就其领域对象的性质而言,它们往往很复杂。

结论

对于此类问题,没有快速而肮脏的解决方法。复杂领域意味着在某些时候必须完成一些额外的工作。 基于序列化 的解决方案(1、3、4),尽管有些现在看起来很容易,但只会将上述额外工作推迟到引入更改的那一刻。在几乎所有情况下,我都会选择更好的灵 active 更改准备(只有第二种解决方案提供 - 如果处理得当)。

关于c# - 用于安排单元测试的序列化对象图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14415077/

相关文章:

c# - 在 asp.net 中是否有替代 <br/> 的方法?

javascript - 如何修复 Jasmine 中的 'TypeError: Cannot redefine property: origin'

javascript - 我为 Freecodecamp 创建了一个 "Cash Register"函数,但出于某种原因,最后两个测试没有通过?

testing - 使用 dbunit 和 jetty 进行集成测试 - dbunit 不填充表

javascript - 在 JEST 中导出 beforeAll 和 afterAll

c# - 防止最大化的 WPF 窗口覆盖任务栏

c# 创建任意长度的通用参数字符串,例如,?,?

unit-testing - 如何为私有(private) clojure 函数编写单元测试?

c# - 如何显示具有焦点外观但不焦点的表单?

angularjs - 如何使用 Jasmine 和 Karma 模拟 angularjs $window.sessionStorage