我第一次嘗試.NET核心,並看到如何在單元測試中使用Moq。開箱即用,在創建控制器,其中ApplicationDbContext是參數的構造函數是這樣的:我如何在.NET核心Moq ApplicationDbContext
public class MoviesController : Controller
{
private readonly ApplicationDbContext _context;
public MoviesController(ApplicationDbContext context)
{
_context = context;
}
這裏的單元測試,我開始測試控制器時:
[TestClass]
public class MvcMoviesControllerTests
{
[TestMethod]
public async Task MoviesControllerIndex()
{
var mockContext = new Mock<ApplicationDbContext>();
var controller = new MoviesController(mockContext.Object);
// Act
var result = await controller.Index();
// Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
但隨後我意識到ApplicationDbContext是一個具體的類,它沒有無參數的構造函數,所以測試不起作用。它給了我錯誤:無法找到無參數的構造函數。
也許這可能是一個更多針對Moq的問題,而不是它與.NET Core相關,但我也是Moq的新手,所以我不知道如何繼續。下面是當我創建項目ApplicationDbContext代碼是如何產生的:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
public DbSet<Movie> Movie { get; set; }
}
需要什麼改變讓我的單元測試會成功嗎?
UPDATE:
我從https://msdn.microsoft.com/en-us/magazine/mt703433.aspx發現,您可以配置EF核心使用內存數據庫進行單元測試。所以我改變我的單元測試看起來像這樣:
[TestMethod]
public async Task MoviesControllerIndex()
{
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseInMemoryDatabase();
var _dbContext = new ApplicationDbContext(optionsBuilder.Options);
var controller = new MoviesController(_dbContext);
// Act
var result = await controller.Index();
// Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
這個測試現在成功了。但是,這是做這件事的正確方法嗎?顯然,我完全消除了用Moq嘲笑ApplicationDbContext!還是有另一種解決方案來解決這個問題使用Moq。
即使使用內存中的DbContext,您也基本上正在進行集成測試,這仍然是必需的。然而,從設計的角度來看,你應該讓你的課程取決於抽象而不是結核。創建一個接口,公開您需要的功能並讓您的具體上下文繼承於此。 – Nkosi
我同意@Nkosi這是現在有效的集成測試。當ApplicationDbContext實現'IdentityDbContext'時,你可能可以將接口注入到你的控制器中,然後模擬它嗎? –
Corporalis