2011-06-30 17 views
0

私はいくつかのデータベースの内容を変更するスポーク/スプリングテストを持っており、そのレコードをどのようにロールバックするのだろうかと思います。テスト後に特定のレコードをロールバックする方法はありますか?

現在、私は生のSQL文を実行し、フィールドのデータを保存し、そのデータを正常にテストした後に復元します。しかし、私の推測は、これは簡単な方法で行うことができるということですか?テストを実行する前に

@ContextConfiguration(locations = "classpath*:applicationContext-test.xml") 
class RepositoryTest extends Specification { 

    @Shared sql = Sql.newInstance("jdbc:sqlserver://...") 
    ResourceRepository resourceRepository; 

    def "Save test"() { 
     setup: 
     // copy the row before we do changes! we need to restore this later on! 
     def row = sql.firstRow("select id, content, status from table-name where id = 12345") 

     when: 
     ... 

     then: 
     .. 

     cleanup: 
     sql.execute(""" 
        update table-name set content = ${row.content}, status = ${row.status} 
        where id = ${row.id} 
        """) 
    } 
} 
+0

あなたが本当にむしろ試験方法がなかった何よりも、特定のレコードをロールバックしたいですか? –

答えて

1

私はこれを行うために見つけた最良の方法は次のとおりです。

  • 開始テスト
  • 開始トランザクション
  • (オプション)テストはDBUnitのようなものを使用する必要が任意のDBのデータをロード
  • 走行テストすべてのDBの操作は同じトランザクション内で発生
  • ロールバック・トランザクション

お知らせ。このトランザクションはテスト終了時にロールバックされるため(例外がスローされた場合でも)、テスト終了時と同じ状態のデータベースが常に開始時に存在する必要があります。

Springには、テストごとにトランザクションを開始してロールバックするためのクラスが用意されています。あなたは春& JUnit4を使用していて、あなたのテストクラスが最も簡単なオプションがある春のクラスを拡張する必要があることを気にしない場合は、春のクラスを拡張したくない場合は、おそらく、AbstractTransactionalJUnit4SpringContextTests

// Location of the Spring config file(s) 
@ContextConfiguration(locations = {"/application-context-test.xml", "classpath*:/application-context-persistence-test.xml"}) 

// Transaction manager bean name 
@TransactionConfiguration(transactionManager = "hsqlTransactionManager", defaultRollback = true) 
@Transactional(propagation=Propagation.REQUIRES_NEW) 
public class MyTransactionalTests extends AbstractTransactionalJUnit4SpringContextTests { 

    @Test 
    public void thisWillRunInATransactionThatIsAutomaticallyRolledBack() {} 
} 

を拡張します注釈を使用する代わりにテストランナーを設定することができます。 Springは、JUnitの他の主要なユニットテストフレームワークや古いバージョンの多くをサポートしています。

+0

SpockはSpringのTestContextフレームワークを直接サポートしているので、基本クラスもカスタムランナーも必要ありません。 @TransactionConfigurationは、bean "transactionManager"の名前を付けるために省略することができます。 GroovyのSqlクラスをSpringのトランザクションと連携させるには、Spring提供のデータソースを使用してGroovyのSqlクラスを初期化する必要があります。SqlクラスがSpringの例外変換を実行しないという事実は、トランザクションがロールバックされる場合に影響を与える可能性があります。 –

0
CREATE TABLE table_name 
(
    id  NUMBER, 
    content NUMBER, 
    status NUMBER 
); 

INSERT INTO table_name 
    VALUES (1, 2, 3); 

INSERT INTO table_name 
    VALUES (4, 5, 6); 

INSERT INTO table_name 
    VALUES (7, 8, 9); 

COMMIT; 

、あなたはVARCHAR2(4000)変数にこのSELECTから結果の文字列を格納し、テスト後にあなただけの文字列を実行する必要があります。

SELECT 'UPDATE TABLE_NAME SET CONTENT = ' 
     || CONTENT 
     || ', STATUS = ' 
     || STATUS 
     || ' WHERE ID = ' 
     || ID 
    FROM TABLE_NAME 
WHERE ID = 1; 

前の例では、バックアップするレコードにID = 1があると仮定しています。 この例の文字列には、次のUPDATEステートメントが含まれています。

UPDATE TABLE_NAME SET CONTENT = 2, STATUS = 3 WHERE ID = 1 
1

テストでGroovyのSqlとSpringのアノテーション(@RunWith、@ContextConfiguration、@Transactional、@Rollback、...)を混在させている場合は、dataSourceをorg.springframework.jdbcでラップすることができます。 datasource.TransactionAwareDataSourceProxy。

<bean id="db-dataSourceReal" 
    class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" value="jdbc/foo" /> 
    <property name="resourceRef" value="true" /> 
    <property name="lookupOnStartup" value="true" /> 
</bean> 

<bean id="db-dataSource" 
    class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> 
    <constructor-arg ref="db-dataSourceReal" /> 
</bean> 

次に、Groovy SqlのデータソースとしてTransactionAwareDataSourceProxyを使用します。たとえば、あなたのテストクラスで、(この場合にはMavenのフェイルセーフプラグインを使用して)

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations=[ 
     "classpath*:applicationContext-test.xml" 
]) 
class SimplePojoDaoIT { 

    @Resource(name="dao-pojoDao") 
    PojoDao pojoDao 

    @Test 
    @Transactional("transactionManager") 
    @Rollback 
    public void testShouldPersistToDB(){ 

     SomePojo pojo = new SomePojo() 
     pojo.with{ 
     id = 5 
     name = 'foo' 
     } 

     pojoDao.persist(pojo) 

     def sql = new Sql(pojoDao.dataSource) 
     sql.rows("select * from POJO_TBL where id = :id", [['id':pojo.id]]).each{ row -> 
//  println row 
     pojo.with{ 
      assertEquals(id, row.ID.longValue()) 
      assertEquals(name, row.NAME) 
     } 
     } 
    } 
} 
関連する問題