单元测试没有数据库:LINQ到SQL [英] Unit Testing without Database: Linq to SQL

查看:195
本文介绍了单元测试没有数据库:LINQ到SQL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用LINQ to SQL存储库来实现。我需要做单元测试,虽然我没有一个数据库。我怎么能写FreezeAllAccountsForUser方法UT?能否请您使用手动嘲讽展示一个例子?

请注意:有一个在领域对象使用的继承映射

请注意:单元测试是用做Visual Studio团队测试


  

从@StuperUser评论。单元测试涉及到从与之交互的其他物体完全隔离code。这意味着,如果code失败,可以肯定的是,故障是与被测code做。要做到这一点,你必须假的这些对象。


code

 公共无效FreezeAllAccountsForUser(INT用户id)
    {
        清单< D​​TOLayer.BankAccountDTOForStatus> bankAccountDTOList =新的List< D​​TOLayer.BankAccountDTOForStatus>();        IEnumerable的< D​​BML_Project.BankAccount>账户= AccountRepository.GetAllAccountsForUser(用户ID);
        的foreach(应收DBML_Project.BankAccount ACC)
        {
            串typeResult = Convert.ToString(acc.GetType());
            字符串baseValue = Convert.ToString(typeof运算(DBML_Project.BankAccount));            如果(String.Equals(typeResult,baseValue))
            {
                抛出新的异常(不正确派生类型);
            }            acc.Freeze();            DTOLayer.BankAccountDTOForStatus presentAccount =新DTOLayer.BankAccountDTOForStatus();
            presentAccount.BankAccountID = acc.BankAccountID;
            presentAccount.Status = acc.Status;
            bankAccountDTOList.Add(presentAccount);        }        IEnumerable的< System.Xml.Linq.XElement> EL = bankAccountDTOList.Select(X =>
                        新System.Xml.Linq.XElement(BankAccountDTOForStatus
                          新System.Xml.Linq.XElement(BankAccountID,x.BankAccountID)
                          新System.Xml.Linq.XElement(状态,x.Status)
                        ));        System.Xml.Linq.XElement根=新System.Xml.Linq.XElement(根,EL);
        //AccountRepository.UpdateBankAccountUsingParseXML_SP(root);
        AccountRepository.Update();    }

库层

 命名空间RepositoryLayer
{
公共接口ILijosBankRepository
{
    System.Data.Linq.DataContext上下文{搞定;组; }
    清单< D​​BML_Project.BankAccount> GetAllAccountsForUser(INT用户ID);
    无效更新();}公共类LijosSimpleBankRepository:ILijosBankRepository
{
    公共System.Data.Linq.DataContext上下文
    {
        得到;
        组;
    }
    公开名单< D​​BML_Project.BankAccount> GetAllAccountsForUser(INT用户ID)
    {
        IQueryable的< D​​BML_Project.BankAccount> queryResultEntities = Context.GetTable&所述; DBML_Project.BankAccount方式>()其中(p值=> p.AccountOwnerID ==用户ID);
        返回queryResultEntities.ToList();
    }
    公共虚拟无效更新()
    {
        //Context.SubmitChanges();
    }}}

域类

 命名空间DBML_Project
{公共部分类的BankAccount
{
    //定义域行为
    公共虚拟无效冻结()
    {
        //没做什么
    }
}公共类FixedBankAccount:的BankAccount
{    公共覆盖无效冻结()
    {
        this.Status =FrozenFA;
    }
}公共类SavingsBankAccount:的BankAccount
{    公共覆盖无效冻结()
    {
        this.Status =FrozenSB;
    }
}
}

自动生成的类由LINQ to SQL的

  [全球:: System.Data.Linq.Mapping.TableAttribute(NAME =dbo.BankAccount)]
[InheritanceMapping(code =固定,类型= ty​​peof运算(FixedBankAccount),ISDEFAULT = TRUE)]
[InheritanceMapping(code =储蓄,类型= ty​​peof运算(SavingsBankAccount))]
公共部分类的BankAccount:INotifyPropertyChanging,INotifyPropertyChanged的


解决方案

版本库的责任是坚持域对象并获取他们的请求。即,它的工作是把对象和反序列化/从某种形式的持久存储的序列化。

因此​​,对于库测试必须要测试的在这种情况下,一个数据块的实存储器。即这些都是集成测试 - 测试您的类与外部DB集成

一旦这个钉,客户端/应用程序的其他部分并没有反对真正的DB工作。他们可以嘲笑资源库,并且具有快速的单元测试。你可以假设是getAccount工作,因为集成测试通过。

更多细节:
通过在Repository对象传递一个构造函数或方法ARG,你打开大门,传递假的,或者是模拟。因此,现在该服务测试可没有一个真正运行的仓库>>没有DB-进入>>快速测试。

 公共无效FreezeAllAccountsForUser(INT用户id,ILijosBankRepository accountRepository)
{
  //你的code作为前
}测试()
{VAR mockRepository =新的模拟< ILijosBankRepository>();
    VAR的服务= //创建一个包含对象FreezeAllAccounts ...    service.FreezeAllAccounts(SOME_USER_ID,mockRepository);    mock.Verify(R => r.GetAllAccountsForUser(SOME_USER_ID);
    mock.Verify(R => r.Update());
}

I have a repository implemented using LINQ to SQL. I need to do Unit Testing though I don't have a database. How can I write the UT for FreezeAllAccountsForUser method? Can you please show an example using manually mocking?

Note: There is inheritance mapping used in domain objects

Note: Unit Testing is to be done using Visual Studio Team Test

Comment from @StuperUser. Unit testing involves completely isolating code from the other objects it interacts with. This means that if the code fails, you can be sure that the failure is to do with the code under test. To do this you have to fake these objects.

CODE

     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();

    }

Repository Layer

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();
    }

}

}

Domain Classes

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";
    }
}  
}

Auto generated Class by 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

解决方案

The Repository responsibility is to persist domain objects and fetch them on request. i.e. it's job is to take an object and deserialize/serialize it to from some form of durable storage.

So tests for the repository have to test against the real storage in this case a DB. i.e. these are integration tests - tests that your class integrates with the external DB.

Once you have this nailed, the rest of the client/app doesn't have to work against the real DB. They can mock the repository and have fast unit tests. You can assume that GetAccount works since the integration tests pass.

More details: By passing in the Repository object as a ctor or method arg, you open the doors for passing in a fake or a mock. Thus now the service tests can run without a real repository >> there is no DB-access >> fast tests.

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());
}

这篇关于单元测试没有数据库:LINQ到SQL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆