[英]Mocking Entity Framework Core context
我嘗試測試我的應用程序,所以我需要模擬我的EF上下文。
我的代碼似乎還可以,但是我有以下異常:
“ System.ArgumentNullException:值不能為空。參數名稱:source”
這是我的測試方法:
var options = new DbContextOptionsBuilder<ProductContext>().Options;
var settings = new SqlSettings
{
InMemory = true
};
var context = new Mock<ProductContext>(options, settings);
var mockTreeService = new TreeService(context.Object);
await mockTreeService.CreateTreeAsync("Testing tree", Guid.NewGuid());
context.Verify(x => x.AddAsync(It.IsAny<Tree>(), CancellationToken.None), Times.Once);
看起來在執行這段代碼期間拋出了此異常
var tree = await _context.Trees
.Include(x => x.Translation)
.FirstOrDefaultAsync(x => x.Translation.Pl == name);
它來自我正在測試的服務
我認為這是由於沒有設置連接字符串。 坦白說,要完全模擬DbContext
有點困難,這就是EF Core團隊提供內存中實現的原因。 為了測試目的,這要容易得多。 只需將您的options
初始化更改為:
var options = new DbContextOptionsBuilder<ProductContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
然后,您需要使用測試數據填充數據庫。 然后,您可以運行其余測試。
注意:如果您使用的是內存數據庫,則不再需要模擬上下文,因此可以刪除該部分代碼。 內存數據庫本質上是一個模擬。
我已經使用了這個https://github.com/huysentruitw/entity-framework-core-mock庫。 非常簡單,可以使用較少的編碼編寫單元測試。
如果您使用的是moq框架,則可以使用大多數Moq方法。
以下是測試DBQuery的示例代碼。
public async Task<Boat> GetByIdAsync(string id)
=> await _boatContext.Boats.Where(x => x.id == id).FirstOrDefaultAsync();
[Fact]
public async Task GetByIdAsync_WhenCalled_ReturnsItem()
{
// Arrange
var models = new[] { new Boat { id = "p1" } };
var dbContextMock = new DbContextMock<BoatContext>();
dbContextMock.CreateDbQueryMock(x => x.Boats, models);
var service = new Properties(dbContextMock.Object);
// Act
var okResult = await service.GetByIdAsync("p1");
// Assert
Assert.IsType<Boat>(okResult.Result);
}
在這里發布可以幫助某人:)
我認為Mock
DbContext
是不正確的。 您應該在測試中mocking
您的repositories
... mocking
DbContext
是您基本上在測試Microsoft's
代碼...這是愚蠢的,因為他們已經這樣做了。 如此反復......所有的數據訪問應該通過repositories
(見Repository模式 ),你應該mocking
那些在您的測試,而不是DbContext
。
嘗試使用我的Moq / NSubstitute擴展名MockQueryable: https : //github.com/romantitov/MockQueryable支持所有Sync / Async操作
//1 - create a List<T> with test items
var users = new List<UserEntity>()
{
new UserEntity,
...
};
//2 - build mock by extension
var mock = users.AsQueryable().BuildMock();
//3 - setup the mock as Queryable for Moq
_userRepository.Setup(x => x.GetQueryable()).Returns(mock.Object);
//3 - setup the mock as Queryable for NSubstitute
_userRepository.GetQueryable().Returns(mock);
還支持DbSet
//2 - build mock by extension
var mock = users.AsQueryable().BuildMockDbSet();
//3 - setup DbSet for Moq
var userRepository = new TestDbSetRepository(mock.Object);
//3 - setup DbSet for NSubstitute
var userRepository = new TestDbSetRepository(mock);
注意:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.