【发布时间】:2016-03-21 17:08:55
【问题描述】:
我是单元测试领域的新手。那么请指导我如何在我的控制器中为基于 ADO.Net 的存储库和操作方法编写单元测试?
我将使用 VS 自己的单元测试框架。
那么请看代码,告诉我哪些类和函数需要通过单元测试?
如果有人告诉我需要单元测试哪个区域以及不需要哪个区域,那将非常有帮助?
如果可能,请编写一些单元测试代码,向我展示如何为动作、学生存储库和学生视图模型编写单元测试。
我是否需要使用 mock 或 vs 自己的单元测试足以测试我的存储库功能?
这是我的基础存储库
namespace DataLayer.Repository
{
public abstract class AdoRepository<T> where T : class
{
private SqlConnection _connection;
public virtual void Status(bool IsError, string strErrMsg)
{
}
public AdoRepository(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
public virtual T PopulateRecord(SqlDataReader reader)
{
return null;
}
public virtual void GetDataCount(int count)
{
}
protected IEnumerable<T> GetRecords(SqlCommand command)
{
var reader = (SqlDataReader) null;
var list = new List<T>();
try
{
command.Connection = _connection;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
list.Add(PopulateRecord(reader));
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
GetDataCount(Convert.ToInt32(reader["Count"].ToString()));
}
}
Status(false, "");
}
catch (Exception ex)
{
Status(true, ex.Message);
}
finally
{
// Always call Close when done reading.
reader.Close();
_connection.Close();
_connection.Dispose();
}
return list;
}
protected T GetRecord(SqlCommand command)
{
var reader = (SqlDataReader)null;
T record = null;
try
{
command.Connection = _connection;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
record = PopulateRecord(reader);
Status(false, "");
break;
}
}
catch (Exception ex)
{
Status(true, ex.Message);
}
finally
{
reader.Close();
_connection.Close();
_connection.Dispose();
}
return record;
}
protected IEnumerable<T> ExecuteStoredProc(SqlCommand command, string CountColName="TotalCount")
{
var reader = (SqlDataReader)null;
var list = new List<T>();
try
{
command.Connection = _connection;
command.CommandType = CommandType.StoredProcedure;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
var record = PopulateRecord(reader);
if (record != null) list.Add(record);
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
GetDataCount(Convert.ToInt32(reader[CountColName].ToString()));
}
}
}
finally
{
// Always call Close when done reading.
reader.Close();
_connection.Close();
_connection.Dispose();
}
return list;
}
}
}
这是我的学生资料库
public class StudentRepository : AdoRepository<Student>
{
public int DataCounter { get; set; }
public bool hasError { get; set; }
public string ErrorMessage { get; set; }
public StudentRepository(string connectionString)
: base(connectionString)
{
}
public IEnumerable<Student> GetAll()
{
// DBAs across the country are having strokes
// over this next command!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents"))
{
return GetRecords(command);
}
}
public Student GetById(string id)
{
// PARAMETERIZED QUERIES!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE Id = @id"))
{
command.Parameters.Add(new ObjectParameter("id", id));
return GetRecord(command);
}
}
public IEnumerable<Student> SaveXML(string strXML, int PageNo,int PageSize,string SortCol,string SortOrder)
{
if (PageNo <= 0) PageNo = 1;
using (var command = new SqlCommand("USP_SaveStudent"))
{
command.Parameters.Add("@Data", SqlDbType.VarChar,-1).Value = strXML;
command.Parameters.Add("@PageNbr", SqlDbType.Int).Value = PageNo;
command.Parameters.Add("@PageSize", SqlDbType.Int).Value = PageSize;
command.Parameters.Add("@SortColumn", SqlDbType.VarChar, 20).Value = SortCol;
command.Parameters.Add("@SortOrder", SqlDbType.VarChar, 4).Value = SortOrder;
return ExecuteStoredProc(command);
}
}
public IEnumerable<Student> Delete(int id, int PageNo, int PageSize, string SortCol, string SortOrder)
{
if (PageNo <= 0) PageNo = 1;
using (var command = new SqlCommand("USP_DeleteStudent"))
{
command.Parameters.Add("@ID", SqlDbType.VarChar, -1).Value = id;
command.Parameters.Add("@PageNbr", SqlDbType.Int).Value = PageNo;
command.Parameters.Add("@PageSize", SqlDbType.Int).Value = PageSize;
command.Parameters.Add("@SortColumn", SqlDbType.VarChar, 20).Value = SortCol;
command.Parameters.Add("@SortOrder", SqlDbType.VarChar, 4).Value = SortOrder;
return ExecuteStoredProc(command);
}
}
public IEnumerable<Student> GetStudents(int PageNo, int PageSize, string SortCol, string SortOrder)
{
//string strSQL = "SELECT * FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
//strSQL += " ORDER BY " + sortCol + " " + sortOrder;
//strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
//var command = new SqlCommand(strSQL);
//return GetRecords(command);
if (SortOrder == "Ascending")
SortOrder = "ASC";
else if (SortOrder == "Descending")
SortOrder = "DESC";
if (PageNo <= 0) PageNo = 1;
using (var command = new SqlCommand("USP_GetStudentData"))
{
command.Parameters.Add("@PageNbr", SqlDbType.Int).Value = PageNo;
command.Parameters.Add("@PageSize",SqlDbType.Int).Value= PageSize;
command.Parameters.Add("@SortColumn", SqlDbType.VarChar, 20).Value = SortCol;
command.Parameters.Add("@SortOrder", SqlDbType.VarChar, 4).Value = SortOrder;
return ExecuteStoredProc(command);
}
}
public override Student PopulateRecord(SqlDataReader reader)
{
return new Student
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateID = Convert.ToInt32(reader["StateID"].ToString()),
StateName = reader["StateName"].ToString(),
CityID = Convert.ToInt32(reader["CityID"].ToString()),
CityName = reader["CityName"].ToString()
};
}
public override void GetDataCount(int count)
{
DataCounter = count;
}
public override void Status(bool IsError, string strErrMsg)
{
hasError = IsError;
ErrorMessage = strErrMsg;
}
}
Student Model
---------------
public class Student
{
public int ID { get; set; }
[Required(ErrorMessage = "First Name Required")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name Required")]
public string LastName { get; set; }
public bool IsActive { get; set; }
public int StateID { get; set; }
public string StateName { get; set; }
public int CityID { get; set; }
public string CityName { get; set; }
}
Student View Model
------------------
public class StudentListViewModel
{
public int StartIndex { get; set; }
public int EndIndex { get; set; }
public int page { get; set; }
public int RowCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
public IList<Student> Students { get; set; }
[Required(ErrorMessage = "State Required")]
public int SelectedStateId { set; get; }
public IList<State> States { get; set; }
[Required(ErrorMessage = "City Required")]
public int SelectedCityId { set; get; }
public IList<City> Cities { get; set; }
public StudentListViewModel()
{
PageSize = 5;
sort = "ID";
sortdir = "ASC";
CurrentPage = 1;
}
public void SetUpParams(StudentListViewModel oSVm)
{
if (oSVm.page == 0)
oSVm.page = 1;
StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
EndIndex = (oSVm.page * oSVm.PageSize);
CurrentPage = (StartIndex - 1) / oSVm.PageSize;
if (string.IsNullOrEmpty(oSVm.sort))
oSVm.sort = "ID";
if (string.IsNullOrEmpty(oSVm.sortdir))
oSVm.sortdir = "ASC";
}
}
Here is few action which i need to test
---------------------------------------
public ActionResult List(StudentListViewModel oSVm)
{
if (Request.IsAjaxRequest())
System.Threading.Thread.Sleep(1000); // just simulate delay of one second
StudentListViewModel SVm = new StudentListViewModel();
SVm.SetUpParams(oSVm);
SVm.Students = _Studentdata.GetStudents(oSVm.page, oSVm.PageSize, oSVm.sort, oSVm.sortdir).ToList();
SVm.States = _Statedata.GetAll().ToList();
SVm.Cities = _Citydata.GetAll().ToList();
SVm.RowCount = _Studentdata.DataCounter;
return View("ListStudents",SVm);
}
[HttpPost]
public ActionResult UpdateStudents(StudentListViewModel oSVm, string Action)
{
if (Request.IsAjaxRequest())
System.Threading.Thread.Sleep(1000); // just simulate delay of one second
StudentListViewModel SVm = new StudentListViewModel();
SVm.SetUpParams(oSVm);
if (Action == "UPDATE")
{
SVm.Students = _Studentdata.SaveXML(new List<Student>(oSVm.Students).ToXml("Students"),
oSVm.page, oSVm.PageSize, oSVm.sort, oSVm.sortdir).ToList();
}
else if (Action == "DELETE")
{
SVm.Students = _Studentdata.Delete(oSVm.Students[0].ID,
oSVm.page, oSVm.PageSize, oSVm.sort, oSVm.sortdir).ToList();
}
SVm.States = _Statedata.GetAll().ToList();
SVm.Cities = _Citydata.GetAll().ToList();
SVm.RowCount = _Studentdata.DataCounter;
return PartialView("_StudentGrid", SVm);
}
[HttpPost]
public ActionResult RefreshStudents(StudentListViewModel oSVm)
{
if (Request.IsAjaxRequest())
System.Threading.Thread.Sleep(1000); // just simulate delay of one second
StudentListViewModel SVm = new StudentListViewModel();
SVm.SetUpParams(oSVm);
SVm.Students = _Studentdata.GetStudents(oSVm.page, oSVm.PageSize, oSVm.sort, oSVm.sortdir).ToList();
SVm.States = _Statedata.GetAll().ToList();
SVm.Cities = _Citydata.GetAll().ToList();
SVm.RowCount = _Studentdata.DataCounter;
return PartialView("_StudentGrid", SVm);
}
[HttpGet]
public JsonResult GetCityName(int StateID)
{
if (Request.IsAjaxRequest())
System.Threading.Thread.Sleep(1000); // just simulate delay of one second
return Json(new {CityList =_Citydata.GetCityByStateId(StateID)} , JsonRequestBehavior.AllowGet);
}
谢谢
【问题讨论】:
标签: c# unit-testing asp.net-mvc-5 repository-pattern