10

私はSpringテストフレームワークを使ってhibernateセッションのsave()メソッドをテストしたいと思っています。 @Test方法は次のとおりです。アクティブなバネトランザクション内でデータをdbにフラッシュする方法はありますか?

@Test 
@Transactional 
public void testSave() { 
User expected = createUser(); 
getGenericDao().currentSession().save(expected); 
User actual = getUser(generatedId); 
assertUsersEqual(expected,actual); 
} 

は、私はデータベースにユーザーをフラッシュします。私は私のユーザーは、この方法の後に、データベースに

getGenericDao().currentSession().save(expected); 

になりたいそれから私は、春のデータフレームワークを使用してデータベースにアクセスして、これは次の行でユーザーを保存取得したい:

User actual = getUser(generatedId); 

私は休止状態を使用しようとしました次のような方法をフラッシュしてください:

currentSession().setFlushMode(MANUAL); 
//do saving here 
currentSession().flush(); 

私のユーザーをデータベースにフラッシュしません! しかし、私は@ Transactional Spring Annotationを使用せず、プログラムによるSpringトランザクションでユーザーを保存すると、私は自分が望むものを達成します。残念ながら、db に保存されたユーザーは、スプリング@Transactionalがないためロールバックされません。したがって、私のテストメソッドは、その後のテストメソッドのdbと動作を変更します。

私は自分のユーザーをdb内のテストメソッド(最後ではない)にフラッシュし、テストメソッドの終わりにdbへのすべての変更をロールバックする必要があります。

@Transactional 
public void doSave(User user){ 
    getGenericDao().currentSession().save(user); 
} 

をそしてtestSave内部にdoSaveは何もしていない呼び出し:

UPDATEの提案は、次のようにメソッドを作成しました。まだ私はこのメソッドを実行した後、dbにユーザーがいません。私はブレークポイントを設定し、コマンドラインから私のdbをチェックする。

更新日お返事ありがとうございます。問題は、メソッドflush()が私のユーザをdatabase.Iに入れないということです。私はIsolation.READ_UNCOMMITTEDを試して、ユーザをデータベースに入れません。 @Testメソッドで春のトランザクションをオフにして、プログラムによるトランザクションで保存するだけで、私が望むことを達成できます。しかし、@Testメソッドは、後続の@Testメソッドのために保存されたユーザーを残してロールバックされません。ここで@Testメソッドは、ユーザーを削除する@Testメソッドは、ロールバックされていないため、ユーザーを保存するように危険ではありません。だから、私はとにかに私のユーザ(または削除)をdbに入れることができない@Testメソッドのトランザクションサポートを跳ね返す必要があります。実際には、@Testメソッドが終了し、@Testメソッドのトランザクションがコミットされた後にのみ、ユーザーはdbに置かれます(または削除されます)。 @Testメソッドの途中でユーザをdbに保存して、@Testメソッドの最後にロールバックします。

ありがとうございました!

+0

GenericDaoクラスも教えてもらえますか? 編集:実際には、私は問題を見ると思います。データが実際にデータベースに保存される前に、現在のトランザクションをコミットする必要があります。つまり、保存するメソッドとロードするメソッドの2つの@ Transactionメソッドが必要です。 –

+0

私が正しく行ったかどうか確認してください –

+0

閉じる。私は非トランザクション関数によって呼び出される2つのトランザクション関数があることを意味します。それはうまくいくはずです... –

答えて

1

flushが機能していない場合は、データベースの分離レベルに大きく依存します。

Isolationは、データベースの属性の1つで、ある操作で加えられた変更が他の同時操作でどのように表示されるかを定義します。

あなたの分離レベルがRead CommittedまたはRepeatable Readに設定されていると思います。

8

最後に、私は以下のソリューションにこだわっ:

まず、私の@Test方法は、スプリング@Transactionalサポート内で実行されていません。どのように危険であるか知るには、this articleを参照してください。次に、@Repository豆を@Testの方法の中で使用する代わりに、@Transactional注釈を使用する@Service豆をオートワイヤする。 奇跡がこの

@Test 
@Transactional(propagation = Propagation.NOT_SUPPORTED) 
public void testSave() { 
    Answer created = createAnswer(); 
    Long generatedId = answerService.save(created); 
//at this moment answer is already in db 
    Answer actual=getAnswerById(generatedId); 
... } 

よう@Test方法は、(ちょうどanswerService.save(created);後の)データベースに私の答えオブジェクトを置き、方法getAnswerByIdがDBに行くと、保存が正しかったかどうかを確認するためにそれを取り出すことです。あなたはまた、importedpackageの世話をする必要があり、私はJdbcTestUtils.executeSqlScript

+1

JdbcTestUtilsを使用する代わりに@DirtiesContextアノテーションを適用できます。 –

0

してデータベースを再作成@Test方法でデータベースに加えられた変更を排除するために
: は、私の場合、私は

輸入をjavax.transaction.Transactional輸入。代わり

インポートorg.springframework.transaction.annotation.Transactionalの

1
  1. について@Transactionalテスト(Spring Pitfalls: Transactional tests considered harmful)を警告して見hereを持っています。私は@org.springframework.test.context.jdbc.Sqlを使って私のサービステストでDBを再設定し、コントローラについては@Transactionalを使用しました。
  2. ConstraintViolationException無効なデータによるコントローラ更新テストは、トランザクションがコミットされたときにのみスローされました。だから私は3つのオプションを見つけました:
    • 2.1 @Commitまたは@Transactional(propagation = Propagation.NEVER)での注釈テスト。 DBの変更に注意してください。
    • 2.2使用TestTransaction

コード:

 TestTransaction.flagForCommit(); 
    TestTransaction.end(); 
  • 2.3使用TransactionTemplate

コード:

@Autowired 
    private PlatformTransactionManager platformTransactionManager; 

    @Test(expected = Exception.class) 
    public void testUpdate() throws Exception { 
     TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager); 
     transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 
     String json = ... 
     transactionTemplate.execute(ts -> { 
      try { 
       mockMvc.perform(put(REST_URL + USER_ID) 
        .contentType(MediaType.APPLICATION_JSON) 
        .content(json)) 
        .andExpect(status().isOk()); 
       ... 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return null; 
     }); 
関連する問題