8

テストデータの生成にはビルダーパターンを使用しています。これらのドメインオブジェクトには、それらの間に関係があります。私たちの機能テストでは、これらのオブジェクトを永続化する必要があります。

このモデルについて考えてみましょう。

ドメインモデル

CIのプレーンインスタンスが必要な場合はaNew().c().build()

私はそれを持続させたいのなら私はしますaNew().c().saveIn(session)

既知のBIを持つCのインスタンスが必要な場合はaNew().c().with(b).build()

さて、あなたはアイデアを得ました。私の問題は、Cを永続化する場合、Bを永続化する必要があるかどうかです。それとも、事前に永続化する必要がありますか?妥当なデフォルトBが必要な場合はどうなりますか?Dを持続させたい場合はどうなりますか?それはすべてのA、B、Cを持続させるべきですか?

もちろん、実際のシステムははるかに複雑です(循環参照がある場合もあります)。複雑なテストデータを永続化するためのベストプラクティスを探しています。

編集:私は言語の壁にぶつかったようです、私の母国語は英語ではないので、あいまいさをお詫びします。詳細は次のとおりです。

  • 私がテストしようとしているのはレガシーコードではありません
  • 単体テストではなく、カバレッジテストを作成しようとしています(その結果、何もモックしません)
  • 私がテストしようとしているソフトウェアは、データベースにある程度のデータが入力されている場合に機能します(すべてのエンティティを使用するわけではありません)。

PS。私は可能なベストプラクティスを見つけるのに苦労しているので、遠慮なく詳細を尋ねてください。私が思いついた最も近いものは次のとおりです。

  1. エンティティの構築中に明示的に設定されたものを追跡します。
  2. 明示的に設定されたエンティティはすでに永続化されていると想定し、永続化しないでください。
  3. 他のすべてを永続化します(独自の永続化機能を使用)。

これは機能しますが、私のスパイダーセンスはうずきます。テストコードにロジックが含まれるため、テストなしで処理するのは非常に複雑になるため、何か間違ったことをしていると思います。

編集2:私は自分自身をより明確にしようとします。ユニットといくつかの統合テストを書き込んで実行しているときは、テストデータが保持されていないため、問題なくメモリに保存されます。

しかし、テストデータを永続化しようとすると、Hibernateはリレーションなしでエンティティを保存できません。

どうすればこの問題を克服できますか?

4

6 に答える 6

3

おそらく、テストのセットアップをより詳細に説明する必要があります。特に、機能テストでこれらのオブジェクトを永続化する必要があるのはなぜですか?実際の永続化操作をテストしていますか?それとも、それはテストを実行することの単なる副作用ですか?テストの一部として永続化されたオブジェクトをロードしますか?

私の問題は、Cを永続化する場合、Bを永続化する必要があるかどうかです。それとも、事前に永続化する必要がありますか?

これは、そもそもなぜ固執しているのかによって異なります。永続層を統合テストする場合は、アプリケーション自体が使用するロジックを使用する必要があります。テストの単なる副作用である場合は、永続層などをモックすることをお勧めします...

于 2009-09-24T13:03:33.650 に答える
1

あなたが解決しようとしている問題をよく理解したかどうかはわかりませんが... XStreamやGoogleのProtocolBuffersなどを使用してグラフ全体をXMLとしてシリアル化するのはどうでしょうか。

于 2009-10-03T21:48:36.473 に答える
1

ドメインでカスケードをより適切に定義する必要があります。テストできない場合、実際のアプリケーションでどのように機能すると思いますか?

例えば:

A-> B:この関係の所有者は誰ですか?BをAに追加しますか、それともその逆ですか?これは、B.SetParent(A)とA.Children.Add(B)の両方を持つことができ、A.Children.Add(B)の場合はBの親をAに設定する実装の詳細にすることができます(同様に他の道の周りに)。するとどうなりますか:

A a1 = new A();
A a2 = new A();
B b = new B();
a1.Children.Add(b);
b.SetParent(a);

ここで決心する必要があります。どのソリューションも完璧ではないため、ここで適用されるのは基本的に個人的な好みとアプリの一貫性です。

ORMを使用すると、プレーンSQL(またはXMLや独自のデータソースなどの他のデータソース)よりも早くこれらの制約の問題に遭遇しますが、プレーンSQLを作成する場合も、問題を考慮する必要があります。

申し訳ありませんが、明確な答えはありませんが、私には、まだ行っていないいくつかの制約を考慮する必要があるようです。

個人的には、DALでNHibernateを使用する場合のリポジトリパターンが好きです。IDisposableからリポジトリを実装し、それぞれにセッションを取得させます。このようにして、「作業単位」パターンをデザインに取り入れます。

それで頑張ってください:)

于 2009-09-30T14:13:40.283 に答える
1

私はあなたの答えをトピックごとに分けました。

私の問題は、Cを永続化する場合、 Bを永続化する必要があるかどうかです。Dを持続させたい場合はどうなりますか?それはすべてのA、B、Cを持続させるべきですか?

これは、適用することを選択したドメイン制約に完全に依存します。たとえば、Cはエンティティであり、Bは値オブジェクトですか?言い換えれば、Cは独自のアイデンティティと人生を持っていますか?Bは主に、その値とその親Cのライフサイクルと密接に関連しているライフサイクルによって識別されますか?

これらのタイプの質問をすることは、何を、いつ、誰が持続するかについての決定を導くのに役立つはずです。

たとえば、CBの両方が関係のみを共有するエンティティである場合、それぞれが意味のある人生と独自のアイデンティティを持っている可能性があるため、それらを独立して永続化することを決定できます。Bが値オブジェクトである場合、オブジェクトの作成/取得/更新/削除を含め、その親エンティティCにその寿命を制御させることを選択する可能性があります。これには、 CがBを永続化することが含まれる可能性があります。

それとも、事前に永続化する必要がありますか?

これに答えるには、オブジェクトの依存関係をマップする必要があります。これらの依存関係は、オブジェクトグラフがRDBMSに永続化されるときに、外部キー制約によって表されることがよくあります。CがBへの参照なしで機能できない場合は、データベースの外部キー制約に準拠するためにBが最初に実行され、トランザクション内で両方を永続化することをお勧めします。上記の考え方に従って、BがCの子エンティティまたは値オブジェクトである場合、CがBを永続化する責任を負うことさえあります。

妥当なデフォルトBが必要な場合はどうなりますか?

Bインスタンスの作成は、 Bファクトリに委任できます。このファクトリロジックをクラス(インスタンスではない)メソッド、コンストラクターとして実装するか、独自のユニットとして分離するかは関係ありません。重要なのは、新しいBの作成と構成が行われる場所が1つあるということです。この場所で、新しくインスタンス化されたオブジェクトのデフォルト構成が実行されます。

これらのタイプの質問をカバーする優れたリソースは、EricEvansによるドメイン駆動設計です。

于 2009-09-30T14:27:57.993 に答える
0
  • あなたのテストはあなたに何を伝えていますか?
  • レガシーアプリケーションをテストしているように聞こえますか?
  • では、コードベースにすでに記述されている機能を取得して、カバレッジテストを作成しようとしていますか?

もう少しフィードバックをお願いします

于 2009-09-24T16:04:00.507 に答える
0

私が見る限り、問題はあなたのドメインにあります(あなたがそれを描いたように)。私が理解している限り、CはBに対して多対1の関係にあり、データベースはnull許容でない外部キーフィールドによってそれを強化しています。一方、質問のコードから、コードには正確に1つのルールが適用されておらず、CインスタンスのBインスタンスを参照するメンバーがnullになる可能性があることがわかりました。私が理解している限り、ドメインモデルはコードと実行時に常に正しいはずなので、このルールがコードで適用された場合(たとえば、C build()メソッドでB参照を要求することにより)、永続性に関する問題-すべてを永続化することができます。

他のもっと汚い解決策は、テストの前にテストを台無しにするすべてのDB制約をプログラムで削除し、後でそれらを復元することです。もちろん、テストと並行して実行されている他のものではDBを完全に使用できなくなりますが、これは、テスト専用にSQLiteやSQL ServerCompactEditionなどの相互接続されたDBを使用することで解決できます。

于 2009-10-04T22:14:02.577 に答える