我尝试测试我的应用,所以我需要模拟我的EF上下文。
我的代码似乎没问题,但我有以下异常:
“System.ArgumentNullException:Value不能为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);
它来自我正在测试的服务
答案 0 :(得分:17)
我认为这是由于没有设置连接字符串。坦率地说,完全模拟DbContext
有点困难,这就是EF Core团队提供内存实现的原因。这对于测试目的而言更容易使用。只需将options
初始化更改为:
var options = new DbContextOptionsBuilder<ProductContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
之后,您需要使用测试数据填充数据库。然后,您可以运行其余的测试。
注意:如果您正在使用内存数据库,则不再需要模拟上下文,因此您可以删除该位代码。内存数据库本身就是一个模拟。
答案 1 :(得分:2)
我已经使用了这个https://github.com/huysentruitw/entity-framework-core-mock库。非常容易,并且可以使用更少的编码来编写单元测试。
如果您使用的是Moq框架,则可以使用大多数Moq方法。
下面是测试DBQuery的示例代码。
CLASS lcl_alv DEFINITION.
PUBLIC SECTION.
METHODS:
generate_alv.
PRIVATE SECTION.
DATA: o_salv_ida TYPE REF TO if_salv_gui_table_ida.
ENDCLASS.
START-OF-SELECTION.
NEW lcl_alv( )->generate_alv( ).
CLASS lcl_alv IMPLEMENTATION.
METHOD generate_alv.
o_salv_ida = cl_salv_gui_table_ida=>create( iv_table_name = 'SBOOK' ).
DATA(lo_layout) = o_salv_ida->default_layout( ).
DATA(lt_sort_rule) = VALUE if_salv_gui_types_ida=>yt_sort_rule(
( field_name = 'FLDATE'
descending = abap_false
is_grouped = abap_true ) ).
lo_layout->set_sort_order( it_sort_order = lt_sort_rule ).
DATA(lt_aggr_rules) = VALUE if_salv_gui_types_ida=>yt_aggregation_rule(
( field_name = 'LUGGWEIGHT'
function = if_salv_service_types=>cs_function_code-sum ) ).
lo_layout->set_aggregations( lt_aggr_rules ).
o_salv_ida->fullscreen( )->display( ).
ENDMETHOD.
ENDCLASS.
在此处发布内容可能会对某人有所帮助:)
答案 2 :(得分:1)
我认为Mock
DbContext
是不正确的。您应该在测试中mocking
repositories
。mocking
DbContext
是您基本上在测试Microsoft's
代码...这很蠢,因为它们已经去做。因此,再次...所有数据访问都应通过repositories
(请参阅Repository Pattern),而您应该是mocking
测试中的用户,而不是DbContext
。>
答案 3 :(得分:0)
尝试使用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);
注意: