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}
                    """)
    }
}
4

3 に答える 3

1

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

  • テストを開始します
  • トランザクションを開始します
  • (オプション)DBUnitなどを使用してテストに必要なDBデータをロードします
  • テストを実行する
  • ロールバックトランザクション

すべてのDB操作が同じトランザクション内で発生することに注意してください。このトランザクションはテストの終了時にロールバックされるため(例外がスローされた場合でも)、データベースはテストの終了時に常に開始時と同じ状態になっている必要があります。

Springは、各テストのトランザクションの開始とロールバックを処理する、非常に便利なクラスをいくつか提供しています。SpringとJUnit4を使用していて、テストクラスがSpringクラスを拡張する必要があることを気にしない場合、最も簡単なオプションはおそらく拡張することです。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クラスを拡張したくない場合は、アノテーションを使用する代わりにテストランナーを構成できます。Springは、他の多くの主要なユニットテストフレームワークと古いバージョンのJUnitもサポートしています。

于 2011-06-30T15:34:36.397 に答える
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>

次に、GroovySQLのdataSourceとして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)
        }
      }
    }
}
于 2011-12-22T19:25:26.173 に答える
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;

テストを実行する前に、このSELECTの結果の文字列をVARCHAR2(4000)変数に格納します。テスト後は、文字列を実行するだけで済みます。

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
于 2011-06-30T14:30:25.707 に答える