背景
- ユーザAはHogeテーブルに参照できるが、Fugaテーブルの更新権限がない
- ユーザBはHogeテーブルに参照できないが、Fugaテーブルの更新権限がある
ユーザBを使ってテストデータの挿入をし、ユーザAでテストしたいロジックを実行したいというケース
@BeforeAll
でDBのデータのバックアップを作成し、@AfterAll
を使って復旧(DELETE、INSERT)する
ただし、データバックアップ→テスト開始の際など、トランザクションが切り替わる間に更新が走るとこの更新内容を消してしまう危険性がある。
サンプル
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@SpringJUnitConfig
public class YourTest {
@Autowired
private JdbcTemplate jdbcTemplateUserB;
@Autowired
private JdbcTemplate jdbcTemplateUserA;
private static List<Map<String, Object>> originalDataUserB; // user-B の元データ
private static List<Map<String, Object>> originalDataUserA; // user-A の元データ
// BeforeAllでテスト前にデータを保存
@BeforeAll
public static void setUpBeforeAll(@Autowired JdbcTemplate jdbcTemplateUserB, @Autowired JdbcTemplate jdbcTemplateUserA) {
// user-B のデータを取得して保存
originalDataUserB = jdbcTemplateUserB.queryForList("SELECT * FROM your_table");
// user-A のデータを取得して保存
originalDataUserA = jdbcTemplateUserA.queryForList("SELECT * FROM your_table");
}
// AfterAllでテスト後に元のデータを復旧
@AfterAll
public static void tearDownAfterAll(@Autowired JdbcTemplate jdbcTemplateUserB, @Autowired JdbcTemplate jdbcTemplateUserA) {
// user-B のデータを元に戻す
jdbcTemplateUserB.update("DELETE FROM your_table");
for (Map<String, Object> data : originalDataUserB) {
// 全てのカラムを動的に処理
StringBuilder columns = new StringBuilder();
StringBuilder values = new StringBuilder();
data.forEach((column, value) -> {
if (columns.length() > 0) {
columns.append(", ");
values.append(", ");
}
columns.append(column);
values.append("?");
});
// INSERT文の作成
String insertSql = String.format("INSERT INTO your_table (%s) VALUES (%s)", columns.toString(), values.toString());
// 値の準備
Object[] insertValues = data.values().toArray();
// INSERTを実行
jdbcTemplateUserB.update(insertSql, insertValues);
}
// user-A のデータを元に戻す
jdbcTemplateUserA.update("DELETE FROM your_table");
for (Map<String, Object> data : originalDataUserA) {
// 全てのカラムを動的に処理
StringBuilder columns = new StringBuilder();
StringBuilder values = new StringBuilder();
data.forEach((column, value) -> {
if (columns.length() > 0) {
columns.append(", ");
values.append(", ");
}
columns.append(column);
values.append("?");
});
// INSERT文の作成
String insertSql = String.format("INSERT INTO your_table (%s) VALUES (%s)", columns.toString(), values.toString());
// 値の準備
Object[] insertValues = data.values().toArray();
// INSERTを実行
jdbcTemplateUserA.update(insertSql, insertValues);
}
}
@Test
@Transactional
public void testMyBatisOperations() {
// user-A でデータ操作
jdbcTemplateUserA.update("UPDATE your_table SET column1 = 'new_value' WHERE column1 = 'old_value'");
// user-A でデータ参照
List<String> data = jdbcTemplateUserA.queryForList("SELECT column1 FROM your_table", String.class);
// アサート例: 'new_value'が存在するか確認
assert(data.contains("new_value"));
}
@Test
@Transactional
public void testAnotherOperation() {
// 他の操作を追加できます
}
}