web-dev-qa-db-ja.com

Entity Frameworkコアコンテキストのモック

私は自分のアプリをテストしようとするので、EFコンテキストをモックする必要があります。

私のコードは問題ないようですが、次の例外があります:

「System.ArgumentNullException:値をnullにすることはできません。パラメータ名:ソース」

これが私のテスト方法です:

  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);

それは私がテストしている私のサービスから来ています

8
bielu000

これは、接続文字列が設定されていないためだと思います。率直に言って、DbContextを完全にモックアウトするのは少し難しいので、EF Coreチームはインメモリ実装を提供しています。これは、テスト目的での作業がはるかに簡単です。 optionsの初期化を次のように変更するだけです。

var options = new DbContextOptionsBuilder<ProductContext>()
                  .UseInMemoryDatabase(Guid.NewGuid().ToString())
                  .Options;

その後、データベースにテストデータを入力する必要があります。その後、残りのテストを実行できます。

注:インメモリデータベースを使用している場合は、コンテキストをモックする必要がなくなるため、コードのその一部を削除できます。インメモリデータベース自体は、本質的にモックです。

25
Chris Pratt

私はこれを使用しました 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);
}

ここに投稿すると、誰かを助けるかもしれません:)

4
cdev

MockDbContextが正しいとは思いません。テストではmockingrepositoriesにする必要があります... mockingDbContextは基本的にテスト中ですMicrosoft'sコード...彼らはすでにそれをしているので、それはばかげています。繰り返しますが、すべてのデータアクセスはrepositoriesRepository Pattern を参照)を経由する必要があり、テストではmockingではなくDbContextである必要があります。

1
Serj Sagan

Moq/NSubstitute拡張MockQueryableを使用してみてください: https://github.com/romantitov/MockQueryable すべての同期/非同期操作をサポート

//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);

注:

  • AutoMapperは1.0.4バージョンからサポートされています
  • 1.1.0バージョンからサポートされるDbQuery
0
R.Titov