24

私の職場の「アーキテクト」から受け継がれた悪い慣行を数年間守り、もっと良い方法があるに違いないと考えた後、私は最近、TDD と DDD について読んでいます。私たちが作成するソフトウェアの複雑さに非常に適しています。

しかし、私が見た TDD サンプルの多くは、ドメイン オブジェクトのメソッドを呼び出してから、オブジェクトのプロパティをテストして、動作が正しく実行されることを確認しています。

一方、業界で尊敬されている何人かの人々 (Greg Young は、CQRS に関する彼の講演で最も顕著です) は、すべての「ゲッター」を削除することによって、各ドメイン オブジェクトを完全にカプセル化することを提唱しています。

したがって、私の質問は次のとおりです。状態の取得が禁止されている場合、ドメインオブジェクトの機能をどのようにテストしますか?

私は何か基本的なことが欠けていると思うので、遠慮なく私をバカと呼んで教えてください - どんなガイダンスも大歓迎です.

4

8 に答える 8

17

あなたが説明しているのは、ドメインオブジェクトの状態をアサートする状態検証です。Mock オブジェクトを利用する 動作検証と呼ばれる TDD のブランチがあります。

動作検証では、呼び出す必要があるメソッドと、必要に応じて呼び出されないメソッドを指定できます。

詳細については、Martin Fowler によるこの記事を参照してください: Mocks Aren't Stubs

于 2009-07-17T20:58:42.463 に答える
9

OK、この回答は 1 年遅すぎます ;-)

ただし、CQRS モデルをテストする場合は、エンティティの状態に関するアサーションではなく、発生したドメイン イベントに関するアサーションを作成できます。

たとえば、次の呼び出しをテストする場合: customer.Rename("Foo") は正しい動作になります。

customer.Name が "foo" に等しいかどうかをテストする代わりに、保留中のイベント ストアに値が "Foo" の保留中の CustomerRename イベントがあるかどうかをテストします。(実装に応じて、uow またはエンティティ イベント リスト内)

于 2010-05-05T19:05:54.390 に答える
4

状態の取得を本当に禁止する場合は、オブジェクトの動作を追跡する機能を持つ TypeMock などのモッキング フレームワークを使用した動作テストに限定されます。純粋な BDD を実行できる場合、理論的には、システム全体の動作だけでシステム全体の正確性を主張できます。

実際には、多くの場合、BDD は単なるステートフル テストよりも脆弱であることがわかりました。特定の理論を求める人もいるかもしれませんが、それはあなたにとってうまくいく場合にのみ機能します. 状態ベースのテストは、今でも私たちが作成するすべての単体テストの 90% を占めており、私たちのチームでは BDD を十分に認識しています。

あなたに最適なことをしてください。

于 2009-07-17T21:03:21.003 に答える
2

ちょっとジャスティン、あなたのように、私は最近、単体テストのために書き込み専用ドメインオブジェクトにゲッターを追加することを考えていましたが、今では私が間違っていたと確信しています。そもそも書き込み専用ドメインのアイデアを取り入れたとすると、ゲッターがいるとしたら、問題が発生します。書き込み専用ドメインの原則では、ドメインオブジェクトからイベントを発生させたり、ドメインオブジェクトが書き込んだプロジェクションから読み取ったりする必要があります。ゲッターを公開すると、オブジェクトの「シェイプ」が公開され始めます。GregYoungが言うように、「ドメインオブジェクトにはシェイプではなく動作があります」。

そうは言っても、私はあなたの同じ質問に苦労しています...書き込み専用ドメインオブジェクトをどのように単体テストしますか?現在の計画は次のとおりです。ドメインオブジェクトに「これらのプロパティが変更されました」というドメインイベントを発生させることを考えています。単体テストでは、「EditCommand」を送信する前に登録します。ここでドメインイベントに関するUdiDahanの投稿を確認し、EricEvansがドメインイベントについて何を言っているかも確認してください。

于 2010-02-22T23:59:00.977 に答える
2

あなたが言及することは状態テストと呼ばれます。動作テストもあります。そのために使用される手法は、依存性注入、制御の反転、およびモックです。

クラスのすべての副作用は、その「依存関係」に対するメソッド呼び出しとして実装されます。つまり、通常はコンストラクターで外部から提供されるオブジェクトです。次に、単体テストで、実際のオブジェクトではなく偽のオブジェクトを提供します。偽のオブジェクトは、その特定のメソッドが呼び出されたかどうかを記憶できます。これは、テストで主張するものです。

特定のインターフェースを実装するクラスを動的に生成することにより、モックオブジェクトの作成を自動化するモックフレームワークが多数存在します。最も人気のあるのはRhino.MocksとMoqです。

于 2009-07-17T21:13:46.223 に答える
2

いくつかのこと。

まず、コードをテスト可能にするために TDD などを実行すると、最終的にクラスが小さくなります。検査できない多くのプライベート プロパティを持つクラスがある場合は、複数のクラスに分割して、よりテストしやすくする可能性が高くなります。

第 2 に、オールドスクール OO アーキテクチャは、言語セーフガードを使用してアクセスできないようにすることで、ソフトウェアを安全にしようとします。TDD アーキテクチャは、コードが実際に何をするかを検証するテストを書くことでソフトウェアをより堅牢にし、プログラムが何をしないかを保証するために言語構造を使用することにあまり重点を置きません。

最後に、プロパティをチェックすることは、コードが本来の動作を行ったことを検証する唯一の方法ではありません。本 xUnit Design Patterns には、他のアプローチが記載されています: http://xunitpatterns.com/Result%20Verification%20Patterns.html

于 2009-07-17T20:58:42.447 に答える
2

システムのパブリック入力メソッドを呼び出し (つまり、入力データをシステムにプッシュします)、システムの出力を取得 (およびアサート) します。私はシステムの内部状態をテストしているのではなく、その公開/可視動作をテストしています:内部実装をテストする必要がありますか、それとも公開動作のみをテストする必要がありますか?

于 2009-07-17T21:04:57.910 に答える
1

私は最終的に次の論文に出くわすまで、同じことを考えていました. 私は、それらが動作検証を実行するための優れた入門書であることに気付きました。

  1. ロールベースのオブジェクトを設計するためのモックとテストの使用
  2. オブジェクトではなくロールをモックする
于 2010-04-27T19:58:31.937 に答える