2016-11-29 1 views
0

Tout en faisant des tests unitaires, je ne suis pas en mesure d'obtenir la collecte de retour de dbset ajouter après nouvelle entité dbset, il jette une exception « collection a été modifiée »Collection a été modifiée, l'opération d'énumération ne peut pas excute en Moq avec EF

Voici ma configuration de code

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

ici, je ne suis pas en mesure de comprendre ce que je fais mal dans ce cas. pour référence que je suis en utilisant ce lien:

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

Répondre

4

La réponse actuellement fournie est incorrecte. Il résout seulement le problème en partie.
La déclaration suivante est incorrecte:

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

Le même Enumerator est retourné pour chaque demande, ce qui conduit au problème que vous pouvez utiliser le recenseur ne une fois parce qu'il n'a pas d'articles dans après .

Ce qui résout en partie le problème est remise à zéro du recenseur chaque fois que lorsque vous appelez la GetEnumerator qui pour vous permet de résoudre parce que vous ne pouvez utiliser le Add -Méthode

Solution: Ce qui résout vraiment le problème est d'utiliser un Lambda lors de la configuration de la GetEnumerator Méthode:

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

Cette partie est très importante: .Returns(() =>query.GetEnumerator()); Parce qu'avec ceci un nouvel énumérateur est renvoyé chaque fois qu'une demande est faite.

+1

Merci, pour la réponse –

0

L'erreur est survenue dans moq Dbset parce que je ne suis pas mise à jour de la référence de GetEnumerator après l'ajout d'une nouvelle entité dans le jeu DB.

public class Utility 
    { 
     public static Mock<DbSet<TEntity>> GenerateMockEntity<TEntity>(List<TEntity> entityList) where TEntity : class 
     { 
      var list = new List<TEntity>(); 
      list.AddRange(entityList); 
      var query = list.AsQueryable(); 
      var entityMockSet = new Mock<DbSet<TEntity>>() { CallBase = true}; 
      entityMockSet.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(query.Provider); 
      entityMockSet.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(query.Expression); 
      entityMockSet.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(query.ElementType); 
      entityMockSet.As<IEnumerable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(query.GetEnumerator()); 
      entityMockSet.Setup(x => x.Add(It.IsAny<TEntity>())).Callback<TEntity>(x => { 
       list.Add(x); 
       entityMockSet.As<IEnumerable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(list.GetEnumerator()); 
      }).Returns<TEntity>(x => x); 
      return entityMockSet; 
     } 
    } 
+0

Cela ne fonctionne que si vous utilisez uniquement la méthode Add, et ne faites pas d'autres foreachs ou similaires sur la collection –