加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 如何在ASP.net MVC中正确测试具有数据库调用的控

发布时间:2020-12-15 23:08:45 所属栏目:asp.Net 来源:网络整理
导读:我正在研究ASP.net MVC 3.0应用程序.我正在使用MSTest和Moq进行单元测试.我已经为我的控制器编写了所有测试方法并运行了那些测试,结果很成功. 现在,我怀疑我是否已经正确地进行了单元测试.因为,几乎我的大多数控制器操作都包含数据库调用. 我不嘲笑他们,我只
我正在研究ASP.net MVC 3.0应用程序.我正在使用MSTest和Moq进行单元测试.我已经为我的控制器编写了所有测试方法并运行了那些测试,结果很成功.

现在,我怀疑我是否已经正确地进行了单元测试.因为,几乎我的大多数控制器操作都包含数据库调用.

我不嘲笑他们,我只使用Moq模拟Session和Request对象.

是否真的有必要模拟数据库调用,因为单元测试意味着测试单个代码单元?我认为带有数据库调用的单元测试控制器违反了上述声明.

如果是这样,任何人都可以解释我如何模拟数据库调用吗?我没有使用任何实体框架.

Updated2:

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

将数据访问代码提取到单独的类(通常称为repositories的类):

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

然后将存储库实现注入控制器(Dependency Injection in .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();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读