本篇介紹Entity Framework 實(shí)體框架的文章已經(jīng)到了第十篇了,對實(shí)體框架的各個(gè)分層以及基類的封裝管理,已經(jīng)臻于完善,為了方便對基類接口的正確性校驗(yàn),以及方便對以后完善或擴(kuò)展接口進(jìn)行回歸測試,那么建立單元測試就有很大的必要,本篇主要介紹如何利用VS創(chuàng)建內(nèi)置的單元測試項(xiàng)目進(jìn)行實(shí)體框架的基類接口測試。
在采用單元測試這個(gè)事情上,很多人可能想到了NUnit單元測試工具和NMock工具進(jìn)行處理,其實(shí)微軟VS里面也已經(jīng)為我們提供了類似的單元測試工具了,可以不需要使用這個(gè)第三方的單元測試工具,經(jīng)試用VS的單元測試工具還是整合性很好,使用非常方便的。
1、實(shí)體框架架構(gòu)及基礎(chǔ)類庫接口
在上次的隨筆《Entity Framework 實(shí)體框架的形成之旅--數(shù)據(jù)傳輸模型DTO和實(shí)體模型Entity的分離與聯(lián)合》里面,我根據(jù)實(shí)體框架中混合模式的框架結(jié)構(gòu),所涉及的架構(gòu)圖形如下所示。

我們從上圖可以看到,整個(gè)框架從下往上分為了幾個(gè)明顯的層次,一個(gè)數(shù)據(jù)訪問層DAL層,一個(gè)是業(yè)務(wù)邏輯層BLL層,一個(gè)是Facade門面層,各個(gè)層的功能不同,這幾個(gè)層中以DAL層最為復(fù)雜一些,涉及到底層多種數(shù)據(jù)庫的抽象實(shí)現(xiàn),由于Entity Framework 實(shí)體框架本身就是對多種數(shù)據(jù)庫的實(shí)現(xiàn)抽象,因此本文重點(diǎn)針對這個(gè)DAL層進(jìn)行單元測試。
其中的實(shí)體框架的公用類庫(WHC.Framework.EF),里面涉及到的IBaseDAL就是數(shù)據(jù)訪問層的基類接口,具體數(shù)據(jù)訪問的抽象實(shí)現(xiàn)就在BaseDAL的基類上。

在IBaseDAL接口里面,定義了很多我們數(shù)據(jù)訪問類需要使用的增刪改查、分頁、統(tǒng)計(jì)、輔助方法等接口,以及各個(gè)方法的異步方法接口,如下所示。
namespace WHC.Framework.EF
{
/// <summary>
/// 數(shù)據(jù)訪問層基類接口
/// </summary>
/// <typeparam name="T">實(shí)體對象類型</typeparam>
public interface IBaseDAL<T> where T : class
{
#region 對象添加、修改、刪除
/// <summary>
/// 插入指定對象到數(shù)據(jù)庫中
/// </summary>
/// <param name="t">指定的對象</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
bool Insert(T t);
/// <summary>
/// 插入指定對象到數(shù)據(jù)庫中(異步)
/// </summary>
/// <param name="t">指定的對象</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
Task<bool> InsertAsync(T t);
/// <summary>
/// 插入指定對象集合到數(shù)據(jù)庫中
/// </summary>
/// <param name="list">指定的對象集合</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
bool InsertRange(IEnumerable<T> list);
/// <summary>
/// 插入指定對象集合到數(shù)據(jù)庫中(異步)
/// </summary>
/// <param name="list">指定的對象集合</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
Task<bool> InsertRangeAsync(IEnumerable<T> list);
/// <summary>
/// 更新對象屬性到數(shù)據(jù)庫中
/// </summary>
/// <param name="t">指定的對象</param>
/// <param name="key">主鍵的值</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
bool Update(T t, object key);
/// <summary>
/// 更新對象屬性到數(shù)據(jù)庫中(異步)
/// </summary>
/// <param name="t">指定的對象</param>
/// <param name="key">主鍵的值</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c></returns>
Task<bool> UpdateAsync(T t, object key);
/// <summary>
/// 根據(jù)指定對象的ID,從數(shù)據(jù)庫中刪除指定對象
/// </summary>
/// <param name="id">對象的ID</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
bool Delete(object id);
/// <summary>
/// 根據(jù)指定對象的ID,從數(shù)據(jù)庫中刪除指定對象(異步)
/// </summary>
/// <param name="id">對象的ID</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
Task<bool> DeleteAsync(object id);
/// <summary>
/// 從數(shù)據(jù)庫中刪除指定對象
/// </summary>
/// <param name="t">指定對象</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
bool Delete(T t);
/// <summary>
/// 從數(shù)據(jù)庫中刪除指定對象(異步)
/// </summary>
/// <param name="t">指定對象</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
Task<bool> DeleteAsync(T t);
/// <summary>
/// 根據(jù)指定條件,從數(shù)據(jù)庫中刪除指定對象
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
bool DeleteByExpression(Expression<Func<T, bool>> match);
/// <summary>
/// 根據(jù)指定條件,從數(shù)據(jù)庫中刪除指定對象(異步)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
Task<bool> DeleteByExpressionAsync(Expression<Func<T, bool>> match);
/// <summary>
/// 根據(jù)指定條件,從數(shù)據(jù)庫中刪除指定對象
/// </summary>
/// <param name="condition">刪除記錄的條件語句</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
bool DeleteByCondition(string condition);
/// <summary>
/// 根據(jù)指定條件,從數(shù)據(jù)庫中刪除指定對象(異步)
/// </summary>
/// <param name="condition">刪除記錄的條件語句</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>。</returns>
Task<bool> DeleteByConditionAsync(string condition);
#endregion
或者一些其他的分頁等復(fù)雜的實(shí)現(xiàn)接口。
#region 返回集合的接口
/// <summary>
/// 返回可查詢的記錄源
/// </summary>
/// <returns></returns>
IQueryable<T> GetQueryable();
/// <summary>
/// 根據(jù)條件表達(dá)式返回可查詢的記錄源
/// </summary>
/// <param name="match">查詢條件</param>
/// <param name="sortPropertyName">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
IQueryable<T> GetQueryable(Expression<Func<T, bool>> match, string sortPropertyName, bool isDescending = true);
/// <summary>
/// 根據(jù)條件表達(dá)式返回可查詢的記錄源
/// </summary>
/// <param name="match">查詢條件</param>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
IQueryable<T> GetQueryable<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合
/// </summary>
/// <returns></returns>
IList<T> GetAll();
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合(異步)
/// </summary>
/// <returns></returns>
Task<IList<T>> GetAllAsync();
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合
/// </summary>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
IList<T> GetAll<TKey>(Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合(異步)
/// </summary>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
Task<IList<T>> GetAllAsync<TKey>(Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合(用于分頁數(shù)據(jù)顯示)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="info">分頁實(shí)體</param>
/// <returns>指定對象的集合</returns>
IList<T> GetAllWithPager(PagerInfo info);
/// <summary>
/// 返回?cái)?shù)據(jù)庫所有的對象集合(用于分頁數(shù)據(jù)顯示,異步)
/// </summary>
/// <param name="info">分頁實(shí)體</param>
/// <returns>指定對象的集合</returns>
Task<IList<T>> GetAllWithPagerAsync(PagerInfo info);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns></returns>
IList<T> Find(Expression<Func<T, bool>> match);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(異步)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns></returns>
Task<IList<T>> FindAsync(Expression<Func<T, bool>> match);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
IList<T> Find<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(異步)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
Task<IList<T>> FindAsync<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(用于分頁數(shù)據(jù)顯示)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="info">分頁實(shí)體</param>
/// <returns>指定對象的集合</returns>
IList<T> FindWithPager(Expression<Func<T, bool>> match, PagerInfo info);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(用于分頁數(shù)據(jù)顯示,異步)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="info">分頁實(shí)體</param>
/// <returns>指定對象的集合</returns>
Task<IList<T>> FindWithPagerAsync(Expression<Func<T, bool>> match, PagerInfo info);
/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(用于分頁數(shù)據(jù)顯示)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <param name="info">分頁實(shí)體</param>
/// <param name="orderByProperty">排序表達(dá)式</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns>指定對象的集合</returns>
IList<T> FindWithPager<TKey>(Expression<Func<T, bool>> match, PagerInfo info, Expression<Func<T, TKey>> orderByProperty, bool isDescending = true);
#endregion
以及更多的方法接口,我們?yōu)榱诵r?yàn)沒有接口都能夠正常工作,就需要對它們進(jìn)行單元測試。
2、在VS里面創(chuàng)建單元測試項(xiàng)目及編寫單元測試代碼
在VS里面創(chuàng)建內(nèi)置的單元測試項(xiàng)目如下所示,在添加新項(xiàng)目里面選擇測試->單元測試項(xiàng)目即可,如下圖所示。

為了方便對基類測試,我們還是需要創(chuàng)建一個(gè)簡單的代表性數(shù)據(jù)庫用來檢查基礎(chǔ)的接口操作。
由于前面的系列,已經(jīng)介紹過了,我們在構(gòu)建數(shù)據(jù)訪問層的時(shí)候,使用的是基于IOC的方式構(gòu)建一個(gè)對象的接口對象,如這樣代碼IFactory.Instance<IUserDAL>()所示。
而單元測試,基本原理就是我們調(diào)用接口,并獲取對應(yīng)的輸出結(jié)果,和我們預(yù)期的值進(jìn)行對比,如果吻合就是正常通過的測試用例。
為了進(jìn)行基礎(chǔ)類庫的單元測試,我們需要根據(jù)實(shí)體框架的結(jié)構(gòu)搭建一個(gè)具體表的對象項(xiàng)目工程,這個(gè)采用代碼生成工具Database2Sharp進(jìn)行生成就可以了,生成的處理操作如下所示。

這樣根據(jù)表快速生成的整個(gè)實(shí)體框架,就是我們所需要的實(shí)體框架項(xiàng)目,具體效果如下所示。

例如我們創(chuàng)建一個(gè)查找記錄的單元測試方法代碼如下所示。
namespace TestFrameworkEF
{
[TestClass]
public class TestBaseDAL
{
private string userId = Guid.NewGuid().ToString();
[TestInitialize]
public void Init()
{
User user = new User() { ID = userId, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
}
[TestCleanup]
public void Cleanup()
{
bool result = IFactory.Instance<IUserDAL>().Delete(userId);
Assert.AreEqual(result, true);
}
[TestMethod]
public void FindByID()
{
User user = IFactory.Instance<IUserDAL>().FindByID(userId);
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
其中上面紅色代碼部分就是單元測試的各種標(biāo)識,包括單元測試類標(biāo)識,以及初始化、退出清除、測試用例的標(biāo)識。
上面案例,我們是在單元測試前,在數(shù)據(jù)庫寫入一條記錄,然后在進(jìn)行各種單元測試用例的運(yùn)行及校驗(yàn),最后退出的時(shí)候,清除我們寫入的記錄。
而記錄的更新和刪除接口,我們具體的單元測試代碼如下所示。
[TestMethod]
public void Update()
{
string newAccount = "Test";
User user = IFactory.Instance<IUserDAL>().FindByID(userId);
user.Account = newAccount;
bool result = IFactory.Instance<IUserDAL>().Update(user, user.ID);
Assert.AreEqual(result, true);
user = IFactory.Instance<IUserDAL>().FindByID(userId);
Assert.IsNotNull(user);
Assert.AreEqual(user.Account, newAccount);
}
[TestMethod]
public void Delete()
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
result = IFactory.Instance<IUserDAL>().Delete(id);
Assert.AreEqual(result, true);
}
最后我們整個(gè)單元測試的測試代碼如下所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WHC.Framework.EF;
using EFCore.IDAL;
using EFCore.Entity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq.Expressions;
using System.Linq;
using WHC.Pager.Entity;
namespace TestFrameworkEF
{
[TestClass]
public class TestBaseDAL
{
private string userId = Guid.NewGuid().ToString();
[TestInitialize]
public void Init()
{
User user = new User() { ID = userId, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
}
[TestCleanup]
public void Cleanup()
{
bool result = IFactory.Instance<IUserDAL>().Delete(userId);
Assert.AreEqual(result, true);
}
[TestMethod]
public void FindByID()
{
User user = IFactory.Instance<IUserDAL>().FindByID(userId);
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void Insert()
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id , Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
user = IFactory.Instance<IUserDAL>().FindByID(id);
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, id);
result = IFactory.Instance<IUserDAL>().Delete(id);
Assert.AreEqual(result, true);
}
[TestMethod]
public void InsertRang()
{
List<User> list = new List<User>();
for(int i = 0; i<3; i++)
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id, Account = "Nunit" + i.ToString(), Password = "Nunit" };
list.Add(user);
}
bool result = IFactory.Instance<IUserDAL>().InsertRange(list);
Assert.AreEqual(result, true);
foreach(User user in list)
{
result = IFactory.Instance<IUserDAL>().Delete(user.ID);
Assert.AreEqual(result, true);
}
}
[TestMethod]
public void Update()
{
string newAccount = "Test";
User user = IFactory.Instance<IUserDAL>().FindByID(userId);
user.Account = newAccount;
bool result = IFactory.Instance<IUserDAL>().Update(user, user.ID);
Assert.AreEqual(result, true);
user = IFactory.Instance<IUserDAL>().FindByID(userId);
Assert.IsNotNull(user);
Assert.AreEqual(user.Account, newAccount);
}
[TestMethod]
public void Delete()
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
result = IFactory.Instance<IUserDAL>().Delete(id);
Assert.AreEqual(result, true);
}
[TestMethod]
public void DeleteByExpression()
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
Expression<Func<User, bool>> expression = p => p.ID == user.ID && p.Account == user.Account;
result = IFactory.Instance<IUserDAL>().DeleteByExpression(expression);
Assert.AreEqual(result, true);
}
[TestMethod]
public void DeleteByCondition()
{
var id = Guid.NewGuid().ToString();
User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" };
bool result = IFactory.Instance<IUserDAL>().Insert(user);
Assert.AreEqual(result, true);
string condition = string.Format("ID ='{0}' ", id);
result = IFactory.Instance<IUserDAL>().DeleteByCondition(condition);
Assert.AreEqual(result, true);
}
[TestMethod]
public void FindSingle()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
User dbUser = IFactory.Instance<IUserDAL>().FindSingle(expression);
Assert.IsNotNull(dbUser);
Assert.AreEqual(dbUser.ID, userId);
}
[TestMethod]
public void GetQueryable()
{
User user = IFactory.Instance<IUserDAL>().GetQueryable().Take(1).ToList()[0];
Assert.IsNotNull(user);
//Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void GetQueryableExpression()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().GetQueryable(expression, "Account").Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void GetQueryableExpression2()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().GetQueryable(expression, s=>s.Account).Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void GetAll()
{
User user = IFactory.Instance<IUserDAL>().GetAll().Take(1).ToList()[0];
Assert.IsNotNull(user);
}
[TestMethod]
public void GetAllOrderBy()
{
User user = IFactory.Instance<IUserDAL>().GetAll(s=>s.Account).Take(1).ToList()[0];
Assert.IsNotNull(user);
}
[TestMethod]
public void GetAllWithPager()
{
PagerInfo pagerInfo = new PagerInfo();
pagerInfo.PageSize = 30;
User user = IFactory.Instance<IUserDAL>().GetAllWithPager(pagerInfo).Take(1).ToList()[0];
Assert.IsNotNull(user);
}
[TestMethod]
public void Find()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().Find(expression).Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void Find2()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().Find(expression, s=>s.Account).Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void FindWithPager()
{
PagerInfo pagerInfo = new PagerInfo();
pagerInfo.PageSize = 30;
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().FindWithPager(expression, pagerInfo).Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void FindWithPager2()
{
PagerInfo pagerInfo = new PagerInfo();
pagerInfo.PageSize = 30;
Expression<Func<User, bool>> expression = p => p.ID == userId;
User user = IFactory.Instance<IUserDAL>().FindWithPager(expression, pagerInfo, s=>s.Account).Take(1).ToList()[0];
Assert.IsNotNull(user);
Assert.AreEqual(user.ID, userId);
}
[TestMethod]
public void GetRecordCount()
{
int count = IFactory.Instance<IUserDAL>().GetRecordCount();
Assert.AreNotEqual(count, 0);
}
[TestMethod]
public void GetRecordCount2()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
int count = IFactory.Instance<IUserDAL>().GetRecordCount(expression);
Assert.AreNotEqual(count, 0);
}
[TestMethod]
public void IsExistRecord()
{
bool result = IFactory.Instance<IUserDAL>().IsExistRecord(userId);
Assert.AreEqual(result, true);
}
[TestMethod]
public void IsExistRecord2()
{
Expression<Func<User, bool>> expression = p => p.ID == userId;
bool result = IFactory.Instance<IUserDAL>().IsExistRecord(expression);
Assert.AreEqual(result, true);
}
[TestMethod]
public void SqlExecute()
{
string newAccount = "newAccount";
string sql = string.Format("update [User] set Account='{0}' Where ID='{1}' ", newAccount, userId);
int count = IFactory.Instance<IUserDAL>().SqlExecute(sql);
Assert.AreEqual(count, 1);
}
[TestMethod]
public void SqlValueList()
{
string sql = string.Format("Select ID From [User] ");
ICollection<string> valueString = IFactory.Instance<IUserDAL>().SqlValueList(sql);
Assert.IsNotNull(valueString);
Assert.IsTrue(valueString.Count > 0);
}
}
}
3、運(yùn)行單元測試
代碼編譯沒有問題后,我們需要檢驗(yàn)我們的單元測試代碼的正確性,那么只需要在VS的測試菜單里面,執(zhí)行下面的操作即可。

最后得到的運(yùn)行結(jié)果如下所示,驗(yàn)證了我們基類代碼的正確性。
