問題は、永続エンティティが機能するかどうかをテストする方法についてです。特にカスケード属性(CascadeType.ALLなど)を持つ@ OneToMany / @ ElementCollection / @ ManyToMany / @ OneToOneを使用した複雑なエンティティマッピングの場合、JPAエンティティマッピングが正しく、すべてが期待どおりに機能するかどうかをテストすることは理にかなっていると思います。また、すべてのFK / PK/Unique制約が満たされていることを確認してください。
これが一般的な質問です。具体的な部分は、SpringTestingFrameworkについてです。以下のコードで、DAOレイヤーがテストしていることがわかりますが、テストメソッドは@Transactionalとしてマークされているため、変更をロールバックする必要があります。これは、必須ではなく、必須ではありません。確かに、変更は実際にデータベース全体で、トランザクションがロールバック用にマークされているため、おそらくすべてがメモリに保持されているため、データは実際にはデータベースに送信されませんか?
さらに重要なのは、account.getId()が0を返すため(idの生成は@SequenceGeneratorを使用して行われる)、このテストが失敗することですが、この値がアカウントのidフィールドに割り当てられることはないようです。このテストは、メソッドに@Rollback(false)の注釈が付けられている場合にのみ合格するため、もちろんロールバックは発生しません。
確かに、この場合、テストに@Transactionalを使用すると、すべてがメモリ内にあるため(少なくとも、flush()が呼び出されない限り)、データベースの制約が機能していることを確認できません。
そして、上記の考えによれば、エンティティの挿入をテストし、挿入が行われたことを確認してから、すべてを初期状態にロールバックして、他のテストを実行するための適切な方法は何ですか?(テストが実行されるたびに@Before内のデータベースをクリーンアップしますか?)
私はDBUnitを使いたくありません。Springを使うと、DBUnitを使う意味がまったくありません。
@ContextConfiguration( locations = {...}) @RunWith(SpringJUnit4ClassRunner.class) public abstract class JpaRepositoryTest { } public class JpaAccountRepositoryTest extends JpaRepositoryTest { @Inject private AccountRepository accountRepository; @Inject private Account account; @Test @Transactional public void createAccount() { accountRepository.save(account); assertEquals(1, account.getId()); // this assertion will be failed, until @Rollback(false) is used } }
2 に答える
2
制約が延期されず、save の呼び出し後にセッションをフラッシュすると、すべてがデータベースに書き込まれ、制約が適用されます。その後、クエリを実行して、エンティティが返されるかどうかを確認できます。ただし、返されるエンティティは、セッションによってメモリに保持されているものになります。
何かが正しく永続化されていることを本当に確認したい場合は、通常、(TransactionTemplate を使用して) 1 つのトランザクションで永続化を実行し、クエリを実行して、トランザクションのコミット後にすべてが問題ないことを確認します。
于 2011-12-24T12:28:59.413 に答える
0
em.flush() と em.clear() を組み合わせて実行できます。em.flush は上記で説明されています。em.clear() は、コンテキストによって現在認識されているすべてのエンティティを切り離します。
この後、最近永続化されたエンティティの検索を試みることができます。これは、それらをコンテキストに追加するかのようになります。つまり、エンティティに対して実際の検索を実行します。SO にここに投稿した質問の例があります。
于 2013-10-19T20:15:26.397 に答える