VS2005環境でのNAgile - テーブル間のリレーションシップのテスト

今日はデータ テーブル間のリレーションシップのテストを行った。

まずこのテストを行う前の状況を説明しておく。

SQL Server 2005の全てのリレーションシップのINSERTおよびUPDATEの指定は、次のようなデフォルト指定になっている。

  • DeleteRuleの指定・・・動作なし
  • UpdateRuleの指定・・・動作なし

よって自動生成された型付DataSetのDataRelationも次のようなデフォルトのままだ。

  • 作成する制約の選択・・・リレーションシップのみ

次に現状のリレーションシップを以下のように変更していくことにする。

  • 外部キーの制約として親レコードが削除されたときは子レコードの外部キーをNULLにする。
  • 外部キーの制約として親レコードが更新されたときは子レコードの内容も更新させる。

このテストは次のような手順で行った。

最初のタスク:外部キーの制約として親レコードが削除されたときは子レコードの外部キーをNULLにする。

  1. テストメソッドを記述してテストが失敗することを確認する。
  2. データベースダイアグラムで対象のリレーションシップを選択してプロパティを開く。
  3. INSERTおよびUPDATEの指定のDeleteRuleの設定で「Nullに設定」を選択する。
  4. 子テーブルの外部キーのNullを許容を「はい」に設定する。
  5. データベースに変更を反映させる。
  6. データセットデザイナで対象のリレーションシップを選択し、リレーションの編集メニューからリレーションシップダイアログを開く。
  7. 作成する制約の選択で「リレーションシップと外部キー制約の両方」を選択する。
  8. ルールの削除で「SetNull」を選択する。
  9. 子DataTableの外部キーフィールドのAllowDBNullをTrueに設定する。
  10. テストを走らせて成功することを確認する。

次のタスク:外部キーの制約として親レコードが更新されたときは子レコードの内容も更新させる。

  1. テストメソッドを記述してテストが失敗することを確認する。
  2. データベースダイアグラムで対象のリレーションシップを選択してプロパティを開く。
  3. INSERTおよびUPDATEの指定のUpdateRuleの設定で「重ねて表示」を選択する。
  4. データベースに変更を反映させる。
  5. データセットデザイナで対象のリレーションシップを選択し、リレーションの編集メニューからリレーションシップダイアログを開く。
  6. UpdateRuleの設定で「Cascade」を選択する。
  7. テストを走らせて成功することを確認する。

以下は作成されたテスト

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data;
using Library.DataAccessLayer;
using Library.DataAccessLayer.LibraryDataSetTableAdapters;
using System.Transactions;

namespace Library.Tests.DataAccessLayer.Relations
{
 [TestClass]
 public class BooksCategoriesRelationTest
 {
  private LibraryDataSet ds_;
  private TransactionScope ts_;
  private CategoriesTableAdapter cta_;
  private BooksTableAdapter bta_;

  [TestInitialize]
  public void CreateTransactionScope()
  {
   ts_ = new TransactionScope();

   ds_ = new LibraryDataSet();

   cta_ = new CategoriesTableAdapter();
   cta_.Fill(ds_.Categories);
   LibraryDataSet.CategoriesRow category = 
    ds_.Categories.AddCategoriesRow(1, "オブジェクト指向型開発");
   cta_.Update(category);

   bta_ = new BooksTableAdapter();
   bta_.Fill(ds_.Books);
   LibraryDataSet.BooksRow book = 
    ds_.Books.AddBooksRow("4-7741-2728-0", "LifeHacks PRESS", 
     "百式の中の人ほか", "なし", category);
   bta_.Update(book);
  }

  [TestCleanup]
  public void DisposeTransactionScope()
  {
   ts_.Dispose();
  }

  [TestMethod]
  public void カテゴリーテーブルのレコードが削除された場合は書籍テーブルのカテゴリーIDはDBNullになるべき()
  {
   LibraryDataSet.CategoriesDataTable existCategoies = 
    cta_.GetDataByCategoryId(1);
   existCategoies[0].Delete();
   cta_.Update(existCategoies[0]);

   LibraryDataSet.BooksDataTable existBooks = 
    bta_.GetDataByIsbn("4-7741-2728-0");

   Assert.IsTrue(existBooks[0].IsCategoryIdNull());   
  }

  [TestMethod]
  public void インメモリでカテゴリーテーブルのレコードが削除された場合でも書籍テーブルのカテゴリーIDはDBNullになるべき()
  {
   LibraryDataSet.CategoriesRow existCategory = 
    ds_.Categories.FindByCategoryId(1);
   existCategory.Delete();

   LibraryDataSet.BooksRow existBook = ds_.Books.FindByIsbn("4-7741-2728-0");

   Assert.IsTrue(existBook.IsCategoryIdNull());
  }

  [TestMethod]
  public void カテゴリーテーブルのカテゴリーIDが更新された場合は書籍テーブルのカテゴリーIDも更新されるべき()
  {
   LibraryDataSet.CategoriesDataTable existCategoies = 
    cta_.GetDataByCategoryId(1);
   existCategoies[0].CategoryId = 2;
   cta_.Update(existCategoies[0]);

   LibraryDataSet.BooksDataTable existBooks = bta_.GetDataByIsbn("4-7741-2728-0");

   Assert.AreEqual<int>(2, existBooks[0].CategoryId);
  }

  [TestMethod]
  public void インメモリでカテゴリーテーブルのカテゴリーIDが更新された場合でも書籍テーブルのカテゴリーIDも更新されるべき()
  {
   LibraryDataSet.CategoriesRow existCategory = 
    ds_.Categories.FindByCategoryId(1);
   existCategory.CategoryId = 2;

   LibraryDataSet.BooksRow existBook = ds_.Books.FindByIsbn("4-7741-2728-0");

   Assert.AreEqual<int>(2, existBook.CategoryId);
  }
 }
}

#リレーションシップ毎にこのようなテストクラスを作成した。