簡體   English   中英

模擬實體框架核心上下文

[英]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);

注意:

  • 從1.0.4版本開始支持AutoMapper
  • 從1.1.0版本開始支持DbQuery

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM