Asp.net-Mvc
如何在具有數據庫呼叫的 ASP.net MVC 中正確測試控制器
我正在開發一個 ASP.net MVC 3.0 應用程序。我正在使用
MSTestwithMoq進行單元測試。我已經為我的控制器編寫了所有的測試方法並執行了這些測試,得到了成功的結果。現在,我懷疑我是否正確地進行了單元測試。因為,幾乎我的大多數控制器操作都包含數據庫呼叫。
我不是在嘲笑他們,我只是在嘲笑
Session和Request使用 Moq 的對象。是否真的有必要模擬數據庫呼叫,因為單元測試意味著測試單個程式碼單元?我認為帶有數據庫呼叫的單元測試控制器違反了上述聲明。
如果是這樣,誰能解釋我如何模擬數據庫呼叫?我沒有使用任何實體框架。
更新2:
[httppost] public void AjaxSave(Model m) { m.update(); // Database call }
您應該提取使數據庫呼叫成為單獨對象的程式碼(查看Single Responsibility Principle)。例如你有控制器
public class PersonController : Controller { public ActionResult Index() { var connectionString = ConfigurationManager.ConnectionStrings["foo"].ConnectionString; using(var connection = new SqlConnection(connectionString)) { string sql = "SELECT Name FROM People"; var command = connection.CreateCommand(sql); var reader = command.ExecuteReader(); List<Person> people = new List<Person>(); while(reader.Read()) { Person p = new Person(); p.Name = reader["Name"].ToString(); people.Add(p); } return View(people); } } }將數據訪問程式碼提取到單獨的類中(通常此類稱為儲存庫):
public class PersonRepository : IPersonRepository { public List<Person> GetAllPeople() { var connectionString = ConfigurationManager.ConnectionStrings["foo"].ConnectionString; using(var connection = new SqlConnection(connectionString)) { string sql = "SELECT Name FROM People"; var command = connection.CreateCommand(sql); var reader = command.ExecuteReader(); List<Person> people = new List<Person>(); while(reader.Read()) { Person p = new Person(); p.Name = reader["Name"].ToString(); people.Add(p); } return people; } } }正如您已經註意到的那樣,我聲明了由數據訪問類實現的抽象:
public interface IPersonRepository { List<Person> GetAllPeople(); // other data access API will go here }使控制器依賴於這個抽象(這很重要 - 抽像很容易模擬):
public class PersonController : Controller { private IPersonRepository _personRepository; public PersonController(IPersonRepository personRepository) { _personRepository = personRepository; } public ActionResult Index() { var people = _personRepository.GetAllPeople(); return View(people); } }然後將儲存庫實現注入控制器(.NET 中的依賴注入)並模擬它以進行測試:
var repositoryMock = new Mock<IPersonRepository>(); var people = new List<People>(); // provide some sample list repositoryMock.Setup(r => r.GetAllPeople()).Return(people); var controller = new PersonController(repositoryMock.Object); var result = (ViewResult)controller.Index(); // Assert here Assert.AreEqual(result.ViewName, "Index"); Assert.AreEqual(result.Model, people); repositoryMock.VerifyAll();