【问题标题】:Moq & EF6 - Mocking EF6 Remove method not removing an objectMoq & EF6 - 模拟 EF6 删除方法不删除对象
【发布时间】:2017-09-11 03:03:07
【问题描述】:

我正在尝试模拟我的 EF6 DbContext,这一切都适用于 AddUpdateFind 方法。但由于未知原因,它不适用于Remove 方法。

理论上,删除后,Students 集合应该只剩下 1 个返回值。但它一直返回 Count - 2。

我设置了 3 个 Moq.Verify 检查以确保所有方法都被调用并且它们确实被执行。但它实际上并没有从学生收藏中删除该项目。

如果我评论了检查计数的Assert.Equal 行,则整个测试通过。

删除 XUnit 方法

[Fact]
public void Delete()
{            
    Mock<DbContexts.MVCWebAppDbContext> dbContext = new Mock<DbContexts.MVCWebAppDbContext>();
    IStudentsService studentService = new StudentsService(dbContext.Object);

    var students = new List<Student>()
    {
        new Student() { StudentID = 1, RefNo = "12456343", FirstName = "John", LastName = "Smith", DateOfBirth = DateTime.Now.AddYears(-10), DateCreated = DateTime.Now },
        new Student() { StudentID = 2, RefNo = "87984564", FirstName = "Pete", LastName = "Luck", DateOfBirth = DateTime.Now.AddYears(-20), DateCreated = DateTime.Now.AddDays(1) }
    };

    var mockSet = new Mock<DbSet<Student>>();
    mockSet.As<IQueryable<Student>>().Setup(m => m.Provider).Returns(students.AsQueryable().Provider);
    mockSet.As<IQueryable<Student>>().Setup(m => m.Expression).Returns(students.AsQueryable().Expression);
    mockSet.As<IQueryable<Student>>().Setup(m => m.ElementType).Returns(students.AsQueryable().ElementType);
    mockSet.As<IQueryable<Student>>().Setup(m => m.GetEnumerator()).Returns(students.AsQueryable().GetEnumerator());

    mockSet.Setup(m => m.Remove(It.IsAny<Student>())).Callback<Student>((entity) => students.Remove(entity));

    dbContext.Setup(c => c.Students).Returns(mockSet.Object);

    int idToDelete = 1;

    dbContext.Setup(s => s.Students.Find(idToDelete)).Returns(students.Single(s => s.StudentID == idToDelete));

    // call delete method now
    studentService.Delete(idToDelete);

    // 1 object deleted, it should return 1
    Assert.Equal(1, students.Count());  // <----- Error here

    dbContext.Verify(s => s.Students.Find(idToDelete), Times.Once);
    dbContext.Verify(s => s.Students.Remove(It.IsAny<Student>()), Times.Once);
    dbContext.Verify(s => s.SaveChanges(), Times.Once);
}

StudentService.cs 删除方法

MVCWebAppDbContext _context;

public StudentsService(MVCWebAppDbContext context)
{
    _context = context;
}

public int Delete(int id)
{
    var objToDelete = _context.Students.Find(id);

    if (objToDelete != null)
    {
        _context.Students.Remove(objToDelete);
        return _context.SaveChanges();
    }

    return -1;
}

你们能帮我解决这个删除方法的模拟吗?

【问题讨论】:

  • Delete 返回什么值?
  • 我已经调试过了,它返回'1'。

标签: c# unit-testing entity-framework-6 moq xunit


【解决方案1】:

替换

mockSet
    .Setup(m => m.Remove(It.IsAny<Student>()))
    .Callback<Student>((entity) => students.Remove(entity));

dbContext
    .Setup(m => m.Students.Remove(It.IsAny<Student>()))
    .Callback<Student>((entity) => students.Remove(entity));

大部分设置是使用DbContext.Students 完成的,它覆盖了DbSet.Remove 上的设置

事实上,您实际上可以删除所有 DbSet 模拟并且测试仍然可以通过

[Fact]
public void Delete() {
    var dbContext = new Mock<DbContexts.MVCWebAppDbContext>();
    IStudentsService studentService = new StudentsService(dbContext.Object);

    var students = new List<Student>()
    {
        new Student() { StudentID = 1, RefNo = "12456343", FirstName = "John", LastName = "Smith", DateOfBirth = DateTime.Now.AddYears(-10), DateCreated = DateTime.Now },
        new Student() { StudentID = 2, RefNo = "87984564", FirstName = "Pete", LastName = "Luck", DateOfBirth = DateTime.Now.AddYears(-20), DateCreated = DateTime.Now.AddDays(1) }
    };

    dbContext
        .Setup(m => m.Students.Remove(It.IsAny<Student>()))
        .Callback<Student>((entity) => students.Remove(entity));

    int idToDelete = 1;

    dbContext
        .Setup(s => s.Students.Find(idToDelete))
        .Returns(students.Single(s => s.StudentID == idToDelete));

    // call delete method now
    studentService.Delete(idToDelete);

    // 1 object deleted, it should return 1
    Assert.AreEqual(1, students.Count());

    dbContext.Verify(s => s.Students.Find(idToDelete), Times.Once);
    dbContext.Verify(s => s.Students.Remove(It.IsAny<Student>()), Times.Once);
    dbContext.Verify(s => s.SaveChanges(), Times.Once);
}

【讨论】:

    猜你喜欢
    • 2014-03-02
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 2018-03-06
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多