Ich bin neu in Moq und möchte es wie einen Backing Store für Daten verwenden - aber ohne die Live-Datenbank zu berühren.Wie gehe ich mit Einheitentesten mit Entity Framework und Moq vor?
Mein Setup ist wie folgt:
- A UnitOfWork alle Repositories enthält und für den Datenzugriff in der gesamten Anwendung verwendet.
- Ein Repository stellt einen direkten Hook in ein DbSet dar, das von einem DbContext bereitgestellt wird.
- Ein DbContext enthält alle DbSets.
Hier ist mein Test so weit:
// 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());
scheint Mein Test erfolgreich zu sein, da es, dass ein Benutzer mit dem Mock DbSet hinzugefügt wurde überprüfen können - aber was muss ich eigentlich tun ist, erhalten diese Daten zurück und führen weitere Aussagen darüber durch (dies ist nur ein Ad-hoc-Test).
Bitte beachten Sie, Test-Frameworks machen mir den Kopf. Außerdem habe ich die Möglichkeit, zu anderen Test-Frameworks zu verschieben, wenn sie einfacher zu bedienen sind.
Vielen Dank.
Update: Hier ist mein Arbeitscode.
Einheit Test
// 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().
}
}
Zeigen Sie Ihren Code für die Mock db Satz zu halten. Sie müssen nur eine Sammlung erstellen, um als Sicherungsspeicher zu fungieren und die Aufzählungs-DB, die mit der Sicherungsauflistung festgelegt wurde, vorzuspielen. – Nkosi
Entschuldigung. Ich habe meinen Beitrag aktualisiert. MockDbSet ist ungeprüft, da ich mir nicht ganz sicher bin, wie alles zusammenpasst. Ich würde bezweifeln, dass die "abfragbare" Variable so für ein DbSet funktioniert. Wie würde ich eine Sammlung erstellen, die als Backing Store fungiert, indem ich mich in das Mock DbSet einnehme? – Rhonage