【问题标题】:ASP.NET MVC moq returns empty listASP.NET MVC moq 返回空列表
【发布时间】:2015-07-21 21:42:38
【问题描述】:

我正在使用 moq 框架来测试我的 MVC 应用程序。我添加了一个通用存储库和工作单元类。当我运行控制器的测试时,它失败了,因为即使我添加了两个元素,模拟也会返回一个空列表(大小为 0)。这是我的测试:

[TestMethod]
        public void Index()
        {
            var repMock = new Mock<IFakultetRepository<Students>>();
            var students = new List<Students>();
            students.Add(new Students() { BI = "10011", Ime = "Pera", Prezime = "Peric", Adresa = "Ulica1", Grad = "Grad1"});
            students.Add(new Students() { BI = "20011", Ime = "Marko", Prezime = "Markovic", Adresa = "Ulica2", Grad = "Grad2" });

            repMock.Setup(x => x.GetEntities()).Returns(students.ToPagedList(1, 5));

            StudentsController controller = new StudentsController(repMock.Object);
            ViewResult result = controller.Index("", "test", "test", 1) as ViewResult;
            var listResult = result.ViewData.Model as PagedList<Students>;
            var list = listResult.ToList();

            Assert.AreEqual(2, list.Count);
}

这是我的通用存储库,它实现了我的通用存储库接口:

public class FakultetRepository<TEntity> : IFakultetRepository<TEntity> where TEntity : class 
    {
        internal FakultetEntities context;
        internal DbSet<TEntity> dbSet;

        public FakultetRepository(FakultetEntities context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }

        public virtual IEnumerable<TEntity> GetEntities()
        {
            return dbSet.ToList();
        }

        public virtual TEntity GetEntityById(object id)
        {
            return dbSet.Find(id);
        }

        public virtual TEntity GetEntityById(string id)
        {
            return dbSet.Find(id);
        }

        public virtual TEntity GetEntityById(object[] id)
        {
            return dbSet.Find(id);
        }

        public virtual void InsertEntity(TEntity entity)
        {
            dbSet.Add(entity);
        }

        public virtual void DeleteEntity(object id)
        {
            TEntity entity = dbSet.Find(id);
            DeleteEntity(entity);
        }

        public virtual void DeleteEntity(TEntity entity)
        {
            if(context.Entry(entity).State == EntityState.Detached)
            {
                dbSet.Attach(entity);
            }
            dbSet.Remove(entity);
        }

        public virtual void UpdateEntity(TEntity entity)
        {
            dbSet.Attach(entity);
            context.Entry(entity).State = EntityState.Modified;
        }
    }

在控制器中,我有一个构造函数,它初始化工作单元并设置其存储库:

public StudentsController(IFakultetRepository<Students> studentRepository)
        {
            this.unitOfWork = new UnitOfWork();
            this.unitOfWork.StudentsRepository = studentRepository;
        }

这是我正在测试的控制器方法:

public ActionResult Index(string sortOrder, string currentFilter, string search, int? page)
        {
            ViewBag.CurrentSort = sortOrder;
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
            ViewBag.BISortParm = sortOrder == "BI" ? "bi_desc" : "BI";
            ViewBag.CitySortParm = sortOrder == "city" ? "city_desc" : "city";

            if (search != null)
            {
                page = 1;
            }
            else
            {
                search = currentFilter;
            }

            ViewBag.CurrentFilter = search;


            var students = from s in unitOfWork.StudentsRepository.GetEntities()
                           select s;

            if (!String.IsNullOrEmpty(search))
            {
                students = students.Where(s => s.Prezime.Contains(search)
                                       || s.Ime.Contains(search)
                                       || s.BI.Contains(search));
            }

            switch (sortOrder)
            {
                case "name_desc":
                    students = students.OrderByDescending(s => s.Prezime);
                    break;
                case "BI":
                    students = students.OrderBy(s => s.BI);
                    break;
                case "bi_desc":
                    students = students.OrderByDescending(s => s.BI);
                    break;
                case "city":
                    students = students.OrderBy(s => s.Grad);
                    break;
                case "city_desc":
                    students = students.OrderByDescending(s => s.Grad);
                    break;
                default:
                    students = students.OrderBy(s => s.Prezime);
                    break;
            }
            int pageSize = 10;
            int pageNumber = (page ?? 1);
            return View("Index", students.ToPagedList(pageNumber, pageSize));
        }

【问题讨论】:

  • students.ToPagedList(1, 5) 最有可能返回您观察到的空列表。我的猜测是,您要返回页面大小为 1 的第 5 页,并且有两个元素,第 5 页没有可显示的内容。

标签: c# .net asp.net-mvc unit-testing moq


【解决方案1】:

您正在创建两个学生:

students.Add(new Students() 
{ 
    BI = "10011", Ime = "Pera", 
    Prezime = "Peric", Adresa = "Ulica1", 
    Grad = "Grad1"
});

students.Add(new Students() 
{ 
    BI = "20011", Ime = "Marko",
    Prezime = "Markovic", Adresa = "Ulica2", 
    Grad = "Grad2" 
});

你正在调用这个控制器方法:

Index(string sortOrder, string currentFilter, string search, int? page)

使用这些值:

result = controller.Index("", "test", "test", 1) as ViewResult;

在控制器方法中,您对调用GetEntities()返回的结果应用过滤器

if (!String.IsNullOrEmpty(search))
{
      students = students.Where(s => s.Prezime.Contains(search)
                                  || s.Ime.Contains(search)
                                  || s.BI.Contains(search));   
 }    

正如我们在上面看到的,search 的值是“test”

因此,假设已调用模拟并返回了学生,那么您在单元测试中没有看到返回值的原因是

它们已被过滤器删除。

【讨论】:

  • 哦,伙计,我一直在应用搜索过滤器,将其删除,它工作正常。不敢相信我错过了,多么愚蠢的错误,现在需要休息一下。 :) 谢谢!
  • 没问题 - 我一直想使用剧透标签 :)
【解决方案2】:

也可以使用 IList 而不是 List 来解决问题。

请注意,您必须在视图中显示属性。

[Required]
    public IList<ListProductViewModel> Products { get; set; }

 @for (int i = 0; i < Model.Products.Count(); i++)
  {
  <tr id=@Model.Products[i].Id>
    <td>@(rowNo++).</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].Name)</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].Description)</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].Price)</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].Tax)</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].MeasureUnit)</td>
    <td>@Html.DisplayFor(modelItem => Model.Products[i].Currency)</td>
    <td>@Html.NumberTextBoxFor(modelItem => Model.Products[i].Quantity)</td>
    <td>@Html.CheckBoxBoxFor(modelItem => Model.Products[i].IsSelected)</td>
  </tr>
  }

【讨论】:

  • 复制粘贴我的代码不起作用,因为我正在使用一些扩展一些经典 MVC 帮助器的 html 帮助器
猜你喜欢
  • 1970-01-01
  • 2011-10-15
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
相关资源
最近更新 更多