2

LINQ to SQL を使用して実装されたリポジトリがあります。データベースはありませんが、単体テストを行う必要があります。FreezeAllAccountsForUser メソッドの UT を作成するにはどうすればよいですか? 手動でモックを使用した例を示していただけますか?

注: ドメイン オブジェクトで使用される継承マッピングがあります。

注: ユニット テストは、Visual Studio Team Test を使用して行う必要があります。

@StuperUser からのコメント。単体テストでは、相互作用する他のオブジェクトからコードを完全に分離します。これは、コードが失敗した場合、その失敗がテスト対象のコードに関係していることを確認できることを意味します。これを行うには、これらのオブジェクトを偽造する必要があります。

コード

     public void FreezeAllAccountsForUser(int userId)
    {
        List<DTOLayer.BankAccountDTOForStatus> bankAccountDTOList = new List<DTOLayer.BankAccountDTOForStatus>(); 

        IEnumerable<DBML_Project.BankAccount> accounts = AccountRepository.GetAllAccountsForUser(userId);
        foreach (DBML_Project.BankAccount acc in accounts)
        {
            string typeResult = Convert.ToString(acc.GetType());
            string baseValue = Convert.ToString(typeof(DBML_Project.BankAccount));

            if (String.Equals(typeResult, baseValue))
            {
                throw new Exception("Not correct derived type");
            }

            acc.Freeze();

            DTOLayer.BankAccountDTOForStatus presentAccount = new DTOLayer.BankAccountDTOForStatus();
            presentAccount.BankAccountID = acc.BankAccountID;
            presentAccount.Status = acc.Status;
            bankAccountDTOList.Add(presentAccount);

        }



        IEnumerable<System.Xml.Linq.XElement> el = bankAccountDTOList.Select(x =>
                        new System.Xml.Linq.XElement("BankAccountDTOForStatus",
                          new System.Xml.Linq.XElement("BankAccountID", x.BankAccountID),
                          new System.Xml.Linq.XElement("Status", x.Status)
                        ));

        System.Xml.Linq.XElement root = new System.Xml.Linq.XElement("root", el);


        //AccountRepository.UpdateBankAccountUsingParseXML_SP(root);
        AccountRepository.Update();

    }

リポジトリ層

namespace RepositoryLayer
{
public interface ILijosBankRepository
{
    System.Data.Linq.DataContext Context { get; set; }
    List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID);
    void Update();

}

public class LijosSimpleBankRepository : ILijosBankRepository
{
    public System.Data.Linq.DataContext Context
    {
        get;
        set;
    }


    public List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID)
    {
        IQueryable<DBML_Project.BankAccount> queryResultEntities = Context.GetTable<DBML_Project.BankAccount>().Where(p => p.AccountOwnerID == userID);
        return queryResultEntities.ToList();
    }


    public virtual void Update()
    {
        //Context.SubmitChanges();
    }

}

}

ドメイン クラス

namespace DBML_Project
{

public  partial class BankAccount
{
    //Define the domain behaviors
    public virtual void Freeze()
    {
        //Do nothing
    }
}

public class FixedBankAccount : BankAccount
{

    public override void Freeze()
    {
        this.Status = "FrozenFA";
    }
}

public class SavingsBankAccount : BankAccount
{

    public override void Freeze()
    {
        this.Status = "FrozenSB";
    }
}  
}

LINQ to SQL による自動生成クラス

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
[InheritanceMapping(Code = "Fixed", Type = typeof(FixedBankAccount), IsDefault = true)]
[InheritanceMapping(Code = "Savings", Type = typeof(SavingsBankAccount))]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged
4

3 に答える 3

5

単純に、あなたはできません。リポジトリ実装の唯一の目的は、データベースと通信することです。したがって、データベーステクノロジは重要であり、統合テストを実行する必要があります。

LINQ toObjectsはLINQtoSQLのスーパーセットであるため、このコードの単体テストは不可能です。SQLに変換できないリポジトリでLINQの機能を使用したため、実際のデータベースを使用すると、グリーンユニットテストが実行されてもランタイム例外が発生する可能性があります。

于 2012-07-05T17:09:02.673 に答える
2

リポジトリの責任は、ドメイン オブジェクトを保持し、要求に応じて取得することです。つまり、オブジェクトを取得し、それを何らかの形式の耐久性のあるストレージにデシリアライズ/シリアライズすることが仕事です。

したがって、リポジトリのテストは、この場合は DB である実際のストレージに対してテストする必要があります。つまり、これらは統合テストです。クラスが外部 DB と統合するテストです。

これが完了したら、残りのクライアント/アプリは実際の DB に対して動作する必要はありません。リポジトリをモックして、単体テストを高速化できます。統合テストに合格したため、GetAccount が機能していると想定できます。

詳細: Repository オブジェクトを ctor またはメソッド arg として渡すことにより、フェイクまたはモックを渡すための扉が開かれます。したがって、実際のリポジトリなしでサービス テストを実行できるようになりました >> DB アクセスはありません >> 高速テスト。

public void FreezeAllAccountsForUser(int userId, ILijosBankRepository accountRepository)
{
  // your code as before
}

test ()
{  var mockRepository = new Mock<ILijosBankRepository>();
    var service = // create object containing FreezeAllAccounts...

    service.FreezeAllAccounts(SOME_USER_ID, mockRepository);

    mock.Verify(r => r.GetAllAccountsForUser(SOME_USER_ID);
    mock.Verify(r => r.Update());
}
于 2012-07-06T06:04:13.593 に答える
0

データ コンテキストで IDbSet インターフェイスを使用し、データ コンテキスト クラスのインターフェイスを抽出することで、これを行うことができます。インターフェイスに対するプログラミングは、単体テスト可能なコードを作成するための鍵です。

これらの linq クエリの単体テストを作成する理由は、論理クエリの単体テストを作成するためです。統合テストは、あらゆる種類の偽陰性の影響を受けます。データベースが適切な状態にない、同時に実行されている他のクエリ、他の統合テストなど。信頼できる統合テストのためにデータベースを十分に分離することは非常に困難です。そのため、統合テストはしばしば無視されます。1つ選ぶ必要がある場合は、単体テストが必要です...

于 2017-01-11T00:36:45.793 に答える