簡體   English   中英

沒有數據庫的單元測試:Linq to SQL

[英]Unit Testing without Database: Linq to SQL

我有一個使用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

簡單地說,你做不到。 存儲庫實現的唯一目的是與數據庫對話。 因此,數據庫技術確實很重要,您應該執行集成測試。

由於LINQ to Objects是LINQ to SQL的超集,因此無法對該代碼進行單元測試。 您可能有一個綠色的單元測試,並且在使用實際數據庫時仍然會遇到運行時異常,因為您在存儲庫中使用了LINQ的功能,該功能無法轉換為SQL。

存儲庫的責任是保留域對象,並根據請求獲取它們。 也就是說,它的工作是從某個持久存儲中獲取一個對象並將其反序列化/序列化為對象。

因此,對於存儲庫的測試必須針對實際存儲(在這種情況下為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());
}

您可以通過在數據上下文中使用IDbSet接口並為數據上下文類提取接口來實現。 對接口進行編程是創建單元可測試代碼的關鍵。

您要為這些linq查詢創建單元測試的原因是要對邏輯查詢進行單元測試。 集成測試易受各種假陰性的影響。 db處於不正確的狀態,其他查詢同時運行,其他集成測試,等等。很難很好地隔離數據庫以進行可靠的集成測試。 這就是為什么集成測試經常被忽略的原因。 如果我必須選一個,我要單元測試...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM