Je suis nouveau sur Moq, et je veux l'utiliser comme un backing store pour les données - mais sans toucher à la base de données en direct.Comment effectuer des tests unitaires avec Entity Framework et Moq?
Ma configuration est la suivante:
- A UnitOfWork contient tous les dépôts, et est utilisé pour l'accès aux données dans toute l'application.
- Un référentiel représente un hook direct dans un DbSet, fourni par un DbContext.
- Un DbContext contient tous les DbSets.
Voici mon test jusqu'à présent:
// ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "[email protected]",
};
var mockSet = new MockDbSet<User>();
var mockContext = new Mock<WebAPIDbContext>();
mockContext.Setup(c => c.Set<User>()).Returns(mockSet.Object);
// ACT
using (var uow = UnitOfWork.Create(mockContext.Object))
{
uow.UserRepository.Add(user);
uow.SaveChanges();
}
// ASSERT
mockSet.Verify(u => u.Add(It.IsAny<User>()), Times.Once());
Mon test semble réussir, car il peut vérifier qu'un utilisateur a été ajouté à la DbSet maquette - mais ce que je dois faire est d'obtenir effectivement ces données et effectuer d'autres affirmations sur ce (il s'agit juste d'un test ad-hoc).
S'il vous plaît, conseillez-moi, les frameworks de tests font leur tête. De plus, j'ai la possibilité de passer à d'autres frameworks de tests s'ils sont plus faciles à utiliser.
Merci.
Mise à jour: Voici mon code de travail.
test unitaire
// ARRANGE
var user = new User()
{
FirstName = "Some",
LastName = "Guy",
EmailAddress = "[email protected]",
};
var mockSet = new MockDbSet<User>();
var mockContext = new Mock<WebAPIDbContext>();
mockContext.Setup(c => c.Set<User>()).Returns(mockSet.Object);
// ACT
using (var uow = UnitOfWork.Create(mockContext.Object))
{
uow.UserRepository.Add(user);
uow.SaveChanges();
}
// ASSERT
mockSet.Verify(u => u.Add(It.IsAny<User>()), Times.Once());
// TODO: Further assertations can now take place by accessing mockSet.BackingStore.
}
MockDbSet
class MockDbSet<TEntity> : Mock<DbSet<TEntity>> where TEntity : class
{
public ICollection<TEntity> BackingStore { get; set; }
public MockDbSet()
{
var queryable = (this.BackingStore ?? (this.BackingStore = new List<TEntity>())).AsQueryable();
this.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(queryable.Provider);
this.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(queryable.Expression);
this.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(queryable.ElementType);
this.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(() => queryable.GetEnumerator());
// Mock the insertion of entities
this.Setup(e => e.Add(It.IsAny<TEntity>())).Returns((TEntity entity) =>
{
this.BackingStore.Add(entity);
return entity;
});
// TODO: Other DbSet members can be mocked, such as Remove().
}
}
Montrez votre code pour le jeu maquette db. Vous avez juste besoin de créer une collection pour faire office de backing store et de simuler l'énumération db définie avec la collection de sauvegarde. – Nkosi
Désolé à ce sujet. J'ai mis à jour mon message. MockDbSet n'a pas été testé, car je ne suis pas tout à fait sûr comment tout cela s'accorde. Je doute que la variable "queryable" fonctionne de cette façon pour un DbSet. Comment pourrais-je créer une collection pour faire office de backing store en se connectant au simulacre de DbSet? – Rhonage