0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

複数のDBユーザでテストしないといけない時の苦肉の策

Last updated at Posted at 2025-04-21

背景

  • ユーザ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() {
        // 他の操作を追加できます
    }
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?