经过几年的不良习俗,从我的工作地点开始了“建筑师”,并认为必须有更好的方法,我最近一直在围绕TDD和DDD阅读,我认为原理和实践将是一个非常适合我们编写的软件的复杂性。

但是,我看到的许多TDD样本都在域对象上调用方法,然后测试对象的属性以确保正确执行的行为。

另一方面,该行业中有几个受人尊敬的人(格雷格·扬(Greg Young)最值得注意的是,他在关于CQRS的谈判中提倡通过删除所有“ Getters”来完全封装每个领域的对象。

因此,我的问题是:如果禁止检索其状态,则如何测试域对象的功能?

我相信我缺少一些基本的东西,所以请随时称我为白痴并启发我 - 任何指导都将不胜感激。

有帮助吗?

解决方案

您所描述的是 国家验证 您在域对象的状态上断言。 TDD的分支称为 行为验证 利用模拟对象。

行为验证允许您指定应调用哪些方法以及如果需要,则未调用哪些方法。

查看马丁·福勒(Martin Fowler)的这篇文章以获取更多详细信息: 模拟不是存根.

其他提示

OK, this answer is one year too late ;-)

But when you want to test CQRS models, you can make assertions on the fired domain events instead of assertions on entity state.

e.g. if you want to test if calling : customer.Rename("Foo") results in the correct behavior.

Instead of test if customer.Name equals "foo", you rather test if there is a pending CustomerRename event with the value "Foo" in your pending event store. (in your uow or in your entity event list depending on implementation)

If you're really going to go as far as to forbid retrieval of state, then you will be limited to behavioural testing, probably through a mocking framework such as TypeMock, which has the power to track the behaviour of your object. If you are able to do pure BDD, then theoretically you can assert the correctness of your entire system just by the way it's behaving.

In practice, I've found BDD to be more brittle in a lot of cases than just stateful testing. While some people might call for a certain theory, it only works if it works for you. State-based testing still makes up 90% of all the unit tests we write, and we're well aware of BDD on our team.

Do what works best for you.

A couple things.

First, when you do things like TDD to make your code testable you end up with smaller class. If you have a class with lots of private properties you can't inspect, theres a good chance it could be broken into multiple classes and made more testable.

Second, oldschool OO architecture tries to make software safe by using language safeguards to prevent things from being accessible. A TDD architecture makes software more robust by writing tests that verify what the code actually does, putting less emphasis on using language constructs to ensure what the program doesn't do.

Last, checking a property is not the only way to validate code did what it was supposed to do. The book xUnit Design Patterns documents other approaches here: http://xunitpatterns.com/Result%20Verification%20Patterns.html

I call a system's public input methods (i.e. I push input data into the system), and then I get (and assert) the system's output. I'm not testing the system's internal state, but rather its public/visible behaviour: Should one test internal implementation, or only test public behaviour?

What you mention is called state testing. There's also behavior testing. The techniques used for that are Dependency Injection, Inversion Of Control, and Mocking:

All side effects of your class are implemented as method invocations on its "dependencies" -- i.e. objects supplied from the outside, usually in constructor. Then, in your unit-test, you supply a fake object instead of a real one. The fake object can remember if its' certain method was called, and that's what you assert in your test.

There exist number of Mocking Frameworks that automate mock object creation by dynamically generating classes that implement a given interface. Most popular are Rhino.Mocks and Moq.

Hey Justin, like you, I was recently thinking about adding getters to my write-only domain object for the sake of unit testing, but now I am convinced I was wrong. Assuming you've bought into the idea of a write-only domain in the first place, then if you have getters at all, you're asking for trouble. The write-only domain principle would want you to fire an event from your domain object, or read from a projection that your domain object wrote, or something like that. Once you expose getters you're starting to expose the object's "shape", and as Greg Young says, "Domain objects have Behavior, not Shape".

That being said, I am struggling with your same question ... how do you unit test a write-only domain object? Here's my current plan: I am thinking of making my Domain Object fire a Domain Event saying "These properties changed", and in my unit test, I'll register for it before I send the "EditCommand". Check out Udi Dahan's post on Domain Events here, and also see what Eric Evans says about Domain Events.

I was wondering the same thing until I finally stumbled upon the following papers. I found them to be great primers on performing behavior verification, especially the first one providing me several "aha moments":

  1. Using Mocks and Tests to Design Role-Based Objects
  2. Mock Roles, Not Objects
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top