Skip to main content
 首页 » 编程设计

c#之集合已修改,枚举操作可能无法在带有 EF 的 Moq 中执行

2024年01月22日26zhenyulu

在进行单元测试时,在 dbset 中添加新实体后我无法从 dbset 取回集合,它会抛出异常“Collection was modified”

这是我的代码设置

[TestMethod] 
[TestCategory("Skill Category")] 
public void Create_Skill_Category() 
{ 
    var category = new SkillCategoryModel() { CategoryId = 3, CategoryName = "Category 3" }; 
    var result = skillManager.SaveSkillCategory(category); 
    Assert.IsNotNull(result, "Category can't be null"); 
    Assert.AreEqual(category.CategoryId, result.CategoryId, "Category id must be equal"); 
    var categoryList = skillManager.GetCategories(); // here exception thrown 
    Assert.IsTrue(categoryList.Count == 3, "Categories List must be contain three category"); 
} 
 
 
private ISkill skillManager; 
[TestInitialize] 
public void Init() 
{ 
    var category = new SkillCategory { CategoryId = 1, CategoryName = "Category 1" }; 
 
    var categories = new List<SkillCategory> 
    {  
        category, 
        new SkillCategory { CategoryId = 2, CategoryName = "Category 2" } 
    }; 
    var categoryMockSet = Utility.GenerateMockEntity(categories); 
    categoryMockSet.Setup(x => x.Add(It.IsAny<SkillCategory>())).Callback<SkillCategory>(x => categories.Add(x)).Returns<SkillCategory>(x => x); 
    var mock = new Mock<WhoEntities>(); 
    mock.Setup(q => q.SkillCategories).Returns(categoryMockSet.Object); 
    mock.CallBase = true; 
    skillManager = new WhoGroup.DML.Managers.SkillManager(mock.Object); 
} 

在这里我无法理解在这种情况下我做错了什么。 作为引用,我正在使用此链接:

Entity Framework 6 and Moq4: Is it possible to have a mocked DbSet retain added data for the duration of its scope?

请您参考如下方法:

下列说法不正确的是:

entityMockSet.As<IEnumerable<TEntity>>() 
    .Setup(m => m.GetEnumerator()).Returns(query.GetEnumerator()); 

每个请求都会返回相同的Enumerator,这会导致您只能一次使用枚举器的问题,因为之后它没有任何项目。

部分解决问题的方法是在每次调用 GetEnumerator 时重置枚举器,这会为您解决问题,因为您可能只使用 Add-Method

解决方案: 真正解决问题的是在设置 GetEnumerator 方法时使用 Lambda:

entityMockSet.As<IEnumerable<TEntity>>() 
    .Setup(m => m.GetEnumerator()).Returns(() => query.GetEnumerator()); 

这部分很重要: .Returns(() => query.GetEnumerator()); 因为有了这个,每次发出请求时都会返回一个新的枚举器。