[英]Mocking Entity Framework Core context
I try to test my app so I need to mock my EF context. 我尝试测试我的应用程序,所以我需要模拟我的EF上下文。
My code seems to be ok, but I have following exception: 我的代码似乎还可以,但是我有以下异常:
"System.ArgumentNullException : Value cannot be null. Parameter name: source"
“ System.ArgumentNullException:值不能为空。参数名称:source”
Here is my test method: 这是我的测试方法:
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);
It looks like that this exception is thrown during executing this piece of code 看起来在执行这段代码期间抛出了此异常
var tree = await _context.Trees
.Include(x => x.Translation)
.FirstOrDefaultAsync(x => x.Translation.Pl == name);
It comes from my service which I'm testing 它来自我正在测试的服务
I think this is due to not having a connection string set. 我认为这是由于没有设置连接字符串。 Frankly, it's a bit difficult to fully mock out
DbContext
, which is why the EF Core team has provided an in-memory implementation. 坦白说,要完全模拟
DbContext
有点困难,这就是EF Core团队提供内存中实现的原因。 This is far easier to work with for testing purposes. 为了测试目的,这要容易得多。 Just change your
options
initialization to: 只需将您的
options
初始化更改为:
var options = new DbContextOptionsBuilder<ProductContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
Afterwards, you'll need to populate the database with your test data. 然后,您需要使用测试数据填充数据库。 Then, you can run the rest of your test.
然后,您可以运行其余测试。
Note: if you're using the in-memory database, you don't need to mock the context anymore, so you can remove that bit of code. 注意:如果您使用的是内存数据库,则不再需要模拟上下文,因此可以删除该部分代码。 The in-memory database is essentially, itself, a mock.
内存数据库本质上是一个模拟。
I have used this https://github.com/huysentruitw/entity-framework-core-mock library. 我已经使用了这个https://github.com/huysentruitw/entity-framework-core-mock库。 Very easy and can write unit test using less coding.
非常简单,可以使用较少的编码编写单元测试。
You can use most of Moq methods if you are using moq framework. 如果您使用的是moq框架,则可以使用大多数Moq方法。
Below is example code for test DBQuerys. 以下是测试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);
}
Posting here this may help someone :) 在这里发布可以帮助某人:)
I don't think it's correct to Mock
the DbContext
. 我认为
Mock
DbContext
是不正确的。 You should be mocking
your repositories
in your testing... mocking
the DbContext
is you basically testing Microsoft's
code... which is dumb because they already do that. 您应该在测试中
mocking
您的repositories
... mocking
DbContext
是您基本上在测试Microsoft's
代码...这是愚蠢的,因为他们已经这样做了。 So again... all of your data access should go through repositories
(see Repository Pattern ) and you should be mocking
those in your testing, not the DbContext
. 如此反复......所有的数据访问应该通过
repositories
(见Repository模式 ),你应该mocking
那些在您的测试,而不是DbContext
。
Try to use my Moq/NSubstitute extension MockQueryable: https://github.com/romantitov/MockQueryable supported all Sync/Async operations 尝试使用我的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 also supported 还支持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);
Note: 注意:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.