4

私は 2 つの jUnit テスト クラスを持っています。1 つは自分のItemServiceクラスをテストするため、もう 1 つは自分のクラスをテストするためLocationServiceです。ItemServiceテストを実行すると、合格します。テストを実行すると、次のLocationServiceエラーで失敗します。

原因: java.sql.SQLException: org.hsqldb.jdbc.Util.throwError(不明なソース) のステートメント [SELECT COUNT(*) FROM locations] にテーブルが見つかりませんorg.hsqldb.jdbc.jdbcConnection.prepareStatement で (不明なソース)

データベースにロードされているスキーマ ファイルがあり、最初に作成されたテーブルがItemService使用されます。同じスキーマ ファイル内にあるにもかかわらず、テストで使用するlocationsテーブルLocationServiceが作成されない可能性があります。

これは私の test-context.xml ファイルにあります:

<jdbc:embedded-database
    id="myTestDB"
    type="HSQL">
    <jdbc:script
        location="classpath:/test-ddl.sql" />
    <jdbc:script
        location="classpath:/test-data.sql" />
</jdbc:embedded-database>

<bean
    id="dataSourceTest"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property
        name="driverClassName"
        value="org.hsqldb.jdbcDriver" />
    <property
        name="url"
        value="jdbc:hsqldb:mem:myTestDB" />
    <property
        name="username"
        value="sa" />
    <property
        name="password"
        value="" />
</bean>

テーブルが見つからないというエラーが発生せずに 1 つのテストが成功し、データベースに存在しないitemsために別のテストが失敗する理由がわかりません。locationsHSQLDB と Hibernate の使用に関する他の投稿を見ましたが、私は Hibernate を使用していません。これらは、test-ddl.sql ファイルで作成しているテーブルです。

CREATE MEMORY TABLE "ITEMS" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "LOCATION_ID" INTEGER NOT NULL,
    "ITEM_TYPE_ID" INTEGER NOT NULL
);

CREATE MEMORY TABLE "ITEM_TYPES" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "ICON_CLASS" VARCHAR(50)
);

CREATE CACHED TABLE "LOCATIONS" (
    "ID" INTEGER NOT NULL IDENTITY,
    "NAME" VARCHAR(50) NOT NULL,
    "PHOTO" LONGVARBINARY,
    "PHOTO_CONTENT_TYPE" VARCHAR(60),
    "PHOTO_WIDTH" INTEGER,
    "PHOTO_HEIGHT" INTEGER
);

また、テーブル作成ステートメントの後にいくつかUNIQUEFOREIGN KEY制約をスキーマに設定しましたが、何かを作成できなかったかどうかは確かにわかります。HSQLDB 1.8.1.3 JAR を使用しています。locationsクエリを実行できないのに、クエリを実行できるのはなぜitemsですか?

編集:この質問に基づいて考えた場合、大文字と小文字の区別の問題がある可能性がありますが、LOCATIONSテーブルから SELECT しようとしても失敗します:

原因: java.sql.SQLException: ステートメントにテーブルが見つかりません [SELECT COUNT(*) FROM LOCATIONS]

編集:私の魔法の作業ItemServiceテスト:

@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager = "transactionManager")
public class ItemServiceTest {
    private EmbeddedDatabase _db;
    private ItemService _svc;

    @Before
    public void setUp() throws Exception {
        _db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
            .setName("myTestDB").build();
        assertThat(_db, is(notNullValue()));
        _svc = new ItemService();
        _svc.setDataSource(_db);
    }

    @After
    public void tearDown() throws Exception {
        _db.shutdown();
    }

    @Test
    public void testGetCount() {
        assertThat(_svc.getCount(), is(not(0)));
    }
}

私の失敗したLocationServiceテストはまったく同じですが、LocationService代わりにItemService. getCount()メソッドは と の両方に表示されLocationServiceますItemService

public int getCount() {
    String sql = "SELECT COUNT(*) FROM " + TABLE_NAME;
    return _jdbcTmpl.queryForInt(sql, (Map<String, Object>)null);
}

TABLE_NAME間で異なりますItemService:

public static final String TABLE_NAME = "ITEMS";

LocationService:

public static final String TABLE_NAME = "LOCATIONS";

と の両方ItemServiceLocationService次のものがあります。

private NamedParameterJdbcTemplate _jdbcTmpl;

@Resource(name = "dataSource")
public void setDataSource(DataSource dataSource) {
    _jdbcTmpl = new NamedParameterJdbcTemplate(dataSource);
}

編集:問題への新たなひねり。私のLocationServiceテストでは、まだ具体化されていない他のテスト方法がいくつかありました。

@Test
public void testFind() {
    fail("Not yet implemented");
}

私のItemServiceテストでは、唯一の@TestメソッドはtestGetCount合格でした。testFind上記をテストクラスに追加すると、テストクラスと同じようにItemService突然testGetCount失敗しますLocationService

原因: java.sql.SQLException: ステートメントにテーブルが見つかりません [SELECT COUNT(*) FROM ITEMS]

編集:static @BeforeClass /@AfterClassメソッドを使用していないとき (つまり、テストでテーブルが見つからなかったとき) にデバッガーをステップスルーすると、次のコンソール出力に気付きました。

2012 年 4 月 10 日 10:22:44 AM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase INFO: 組み込みデータベース 'myTestDB' を作成しています 2012 年 4 月 10 日 10:22:44 AM org.springframework.jdbc.datasource.init. ResourceDatabasePopulator executeSqlScript INFO: クラスパス リソースから SQL スクリプトを実行しています [test-ddl.sql] 2012 年 4 月 10 日 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: クラスパス リソースから SQL スクリプトを実行しました[test-ddl.sql] で 30 ミリ秒。2012 年 4 月 10 日 10:22:44 AM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: クラスパス リソースから SQL スクリプトを実行 [test-data.sql] 2012 年 4 月 10 日 10:22:44 AM org. springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript 情報: クラスパス リソース [test-data.sql] からの SQL スクリプトの実行が 46 ミリ秒で完了しました。2012 年 4 月 10 日 10:22:55 AM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase INFO: 組み込みデータベース 'myTestDB' を作成しています 2012 年 4 月 10 日 10:23:08 AM org.springframework.jdbc.datasource.embedded. EmbeddedDatabaseFactory initDatabase INFO: 組み込みデータベース 'myTestDB' を作成しています

したがって、データベースをセットアップし、最初に create-tables および populate-tables スクリプトを実行するように見えます。その後、再初期_db化すると、スクリプトは再度実行されません。したがって、後続のテスト メソッド用のテーブルは存在しません。したがって、Spring にこれらのスクリプトを毎回強制的に再実行させる方法を見つけることができれば、セットアップ メソッドとティアダウン メソッドにインスタンス メソッドを@Before使用する方法に戻ることができます。@After

4

2 に答える 2

2

addScriptが答えでした。test-context.xml から初期化スクリプトを削除したので、jdbc:embedded-databaseタグは次のようになります。

<jdbc:embedded-database
    id="myTestDB"
    type="HSQL" />

setUp()テスト クラスのメソッドで、_db初期化を次のように変更しました。

_db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
    .setName("myTestDB").addScript("test-ddl.sql")
    .addScript("test-data.sql").build();

mysetUpとメソッドは、それぞれとtearDownの注釈が付けられたインスタンス メソッドのままです。デバッガーを使用すると、テストごとに 2 つの初期化 SQL スクリプトが実行されたことを示すコンソール出力が表示され、テストごとにテーブルが存在します。@Before@After

于 2012-04-10T14:40:55.353 に答える
1

@BeforeClassそしてstatic!テスト クラスを変更して、次のセットアップ メソッドとティアダウン メソッドを使用しました。

private static EmbeddedDatabase _db;
private static LocationService _svc;

@BeforeClass
public static void setUp() throws Exception {
    _db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
        .setName("myTestDB").build();
    assertThat(_db, is(notNullValue()));
    _svc = new LocationService();
    _svc.setDataSource(_db);
}

@AfterClass
public static void tearDown() throws Exception {
    _db.shutdown();
}

これで、クラス内の他のテストがあっても、私のテストItemServiceとテストの両方が合格になりました。以前に発生していた「ステートメントにテーブルが見つかりません」というエラーは、すべてのテストの前のセットアップとクラス内のすべてのLocationServiceテストのセットアップの前に、少し奇妙に思えます...

于 2012-04-09T20:36:21.830 に答える