私は自分のアプリをテストしようとするので、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);
それは私がテストしている私のサービスから来ています
これは、接続文字列が設定されていないためだと思います。率直に言って、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 Pattern を参照)を経由する必要があり、テストではmocking
ではなくDbContext
である必要があります。
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);
注: