Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 使用ASP.net核心MVC应用程序中的列表为View()创建单元测试_Entity Framework_Unit Testing_Asp.net Core_Asp.net Core Mvc_Moq - Fatal编程技术网

Entity framework 使用ASP.net核心MVC应用程序中的列表为View()创建单元测试

Entity framework 使用ASP.net核心MVC应用程序中的列表为View()创建单元测试,entity-framework,unit-testing,asp.net-core,asp.net-core-mvc,moq,Entity Framework,Unit Testing,Asp.net Core,Asp.net Core Mvc,Moq,我是单元测试新手。我有一个控制器-studentscoontroller和依赖注入,还有我的Index()方法: public class StudentsController : Controller { public readonly UniversityContext _context;//Database public StudentsController(UniversityContext context) { _context = contex

我是单元测试新手。我有一个控制器-
studentscoontroller
和依赖注入,还有我的
Index()
方法:

public class StudentsController : Controller
{
    public readonly UniversityContext _context;//Database
    public StudentsController(UniversityContext context)
    {
        _context = context;    
    }//Constructor with database
    // GET: Students
    public async Task<IActionResult> Index()
    {
        return View(await _context.Students.ToListAsync());
    }
}
公共类学生控制器:控制器
{
公共只读大学上下文_context;//数据库
公立学生控制员(大学上下文)
{
_上下文=上下文;
}//带数据库的构造函数
//获得:学生
公共异步任务索引()
{
返回视图(wait_context.Students.toListSync());
}
}
接下来,我需要编写一个正确的单元测试代码,如果:

1) 视图()与我的学生有一个列表

2) 对学生的查询不为空

我读过关于模拟对象的书,但我不知道如何编写正确的代码。到目前为止我编写的代码:

public class StudentsControllerTests
{
    [Fact]
    public async Task Index_ReturnsAViewResult_WithAListOfStudents()
    {
        var mockRepo = new Mock<UniversityContext>();
        mockRepo.Setup(repo => repo.Students.ToList()).Returns(GetTestStudents());//There i get following error:Expression references a method that does not belong to the mocked object
        var controller = new StudentsController(mockRepo.Object);

        // Act
        var result = controller.Index();

        //// Assert
        var viewResult = Assert.IsType<ViewResult>(result);
        var model = Assert.IsAssignableFrom<IEnumerable<Student>>(
            viewResult.ViewData.Model);
        Assert.NotNull(model);//Second Condition

    }
    public List<Student> GetTestStudents()
    {
        var sessions = new List<Student>();
        sessions.Add(new Student()
        {
            bDate = new DateTime(1994, 7, 2),
            Name = "Test One"
        });
        sessions.Add(new Student()
        {
            bDate = new DateTime(1995, 7, 1),
            Name = "Test Two"
        });
        return sessions;
    }
}
公共类学生控件测试
{
[事实]
公共异步任务索引_ReturnsAViewResult_with alistofstudents()
{
var mockRepo=new Mock();
mockRepo.Setup(repo=>repo.Students.ToList()).Returns(GetTestStudents());//在这里我得到了以下错误:表达式引用了不属于模拟对象的方法
var controller=newstudentscocontroller(mockRepo.Object);
//表演
var result=controller.Index();
////断言
var viewResult=Assert.IsType(结果);
var model=Assert.IsAssignableFrom(
viewResult.ViewData.Model);
Assert.NotNull(model);//第二个条件
}
公共列表GetTestStudents()
{
var sessions=新列表();
sessions.Add(新学生()
{
b日期=新的日期时间(1994,7,2),
Name=“测试一”
});
sessions.Add(新学生()
{
b日期=新的日期时间(1995,7,1),
Name=“测试二”
});
返回会议;
}
}

有人能给我解释一下,如何更正我的代码吗?

您只需要模拟上下文的成员,在本例中是
.Students
属性
ToList
是对属性调用的扩展方法,不能被moq模拟

另外,
.Students
是一个DbSet,也需要被模仿

使用此答案中的测试类:

派生了以下通用扩展方法

public static class MockDbSetExtensions {
    public static Mock<DbSet<T>> AsDbSetMock<T>(this IEnumerable<T> list) where T : class {
        IQueryable<T> queryableList = list.AsQueryable();
        Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
        return dbSetMock;
    }

    public static Mock<DbSet<T>> ToAsyncDbSetMock<T>(this IEnumerable<T> source)
        where T : class {        
        var data = source.AsQueryable();        
        var mockSet = new Mock<DbSet<T>>();        
        mockSet.As<IAsyncEnumerable<T>>()
            .Setup(m => m.GetEnumerator())
            .Returns(new TestAsyncEnumerator<T>(data.GetEnumerator()));        
        mockSet.As<IQueryable<T>>()
            .Setup(m => m.Provider)
            .Returns(new TestAsyncQueryProvider<T>(data.Provider));        
        mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
        mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
        mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator());        
        return mockSet;
    }

}


有一个问题。“无法从列表转换为Microsoft.EntityFrameworkCore.DbSet”@Eldar您是对的,我犯了一个错误。更新答案now@Eldar那
ToListAsync
也会给你带来一些麻烦。现在我得到了以下错误:非虚拟(在VB中可重写)成员上的设置无效:repo=>repo。Students@Eldar检查DbContext并确保Students属性是虚拟的
 mockRepo.Setup(repo => repo.Students.ToList()).Returns(GetTestStudents());
var studentsMockedDbSet = GetTestStudents().ToAsyncDbSetMock();
mockRepo.Setup(repo => repo.Students).Returns(studentsMockedDbSet.Object);