У меня есть следующие настройки:метод издевались DbSet бросает NotImplementedException при вызове внутри контроллера
DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public virtual DbSet<Album> Album { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Модель:
public class Album
{
public int AlbumID { get; set; }
[StringLength(150)]
public string Title { get; set; }
}
Контроллер:
public class AlbumController : Controller
{
ApplicationDbContext db = new ApplicationDbContext();
public AlbumController(ApplicationDbContext injectDb)
{
db = injectDb;
}
// POST: Albums/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult DeleteConfirmed(int id)
{
Album album = db.Album.Find(id);
db.Album.Remove(album);
db.SaveChanges();
return RedirectToAction("Index");
}
}
я написал тест блока с помощью Moq и XUnit проверить функциональность DeleteConfirmed:
public class AlbumsControllerTests
{
public static Mock<DbSet<T>> MockDbSet<T>(List<T> inputDbSetContent) where T : class
{
var DbSetContent = inputDbSetContent.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(DbSetContent.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(DbSetContent.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(DbSetContent.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => inputDbSetContent.GetEnumerator());
dbSet.Setup(m => m.Add(It.IsAny<T>())).Callback<T>((s) => inputDbSetContent.Add(s));
dbSet.Setup(m => m.Remove(It.IsAny<T>())).Callback<T>((s) => inputDbSetContent.Remove(s));
return dbSet;
}
[Fact]
public void DeleteConfirmedTest()
{
// Arrange
var mockAlbumSet = MockDbSet(new List<Album> { });
Mock<ApplicationDbContext> sutDbContext = new Mock<ApplicationDbContext>() { CallBase = true };
sutDbContext.Setup(m => m.Album).Returns(mockAlbumSet.Object);
// Check if Album.Remove works inside this test
var albumToBeDeleted = new Album() { AlbumID = 1, Title = "TestAlbumName" };
sutDbContext.Object.Album.Add(albumToBeDeleted);
Assert.Equal(1, (from a in sutDbContext.Object.Album select a).Count());
sutDbContext.Object.Album.Remove(albumToBeDeleted);
Assert.Equal(0, (from a in sutDbContext.Object.Album select a).Count());
// Actual Test
sutDbContext.Object.Album.Add(albumToBeDeleted);
sutDbContext.Setup(m => m.Album.Find(It.IsAny<int>()))
.Returns(albumToBeDeleted);
AlbumController sut = new AlbumController(sutDbContext.Object);
var output = sut.DeleteConfirmed(1); // Throws NotImplementedException
// Assert
Assert.Equal(0, (from a in sutDbContext.Object.Album select a).Count());
}
}
Испытание бросает следующее исключение на db.Album.Remove (альбом) в DeleteConfirmed:
System.NotImplementedException: Элемент 'Удалить' не был выполненный по типу 'DbSet
1Proxy' which inherits from 'DbSet
1'. Тест удваивает для «DbSet`1» должен обеспечить реализацию методов и свойства, которые используются.
Как вы можете видеть в теле метода MockDbSet, я установка Удалить метод для моего Мок и он прекрасно работает в тестовом модуле. Можете ли вы объяснить мне, почему он не работает внутри контроллера?
Кажется, вы добавляете некоторую реализацию DbContext в свой контроллер, можете ли вы добавить код, который показывает, какой из них? –
@raderick Я вставляю ApplicationDbContext mock (вы можете проверить его исходный код в верхней части). Инициализация находится в тесте: AlbumController (sutDbContext.Object). Это тот же DbContext, который я использовал в тестовом теле. – Outshined
Тестовый код выглядит странно, в строках после '// Проверяем, работает ли Album.Remove внутри этого теста', вы проверяете свои ложные настройки, что неверно. Ваш 'sut.DeleteConfirmed' также частично проверяет ваши настройки Mock. Я бы посоветовал вам переключить DbSet на IDbSet и использовать 'dbSetMock.Verify (x => x.Удалить (albumToBeDeleted)) ', чтобы проверить, что этот код вызывается без проверки каких-либо деталей реализации. –