使用带有NSubstitte、xunit和Dapper的asp.net核心7,我得到了如下代码
控制器
public async Task UpdateStatus(AuthorityStatusUpdateInputDto input)
{
int tenantId = AbpSession.GetTenantId();
using var connection = _dapperContextBuilder.CreateConnection();
var query = _dapperContextBuilder.QueryBuilder(new {Id = input.Id, TenantId = tenantId},
"SELECT TOP 1 * FROM Authority");
Authority authority = await connection.QueryFirstOrDefaultAsync<Authority>(query.Item1, query.Item2);
authority.Status = input.Status;
await _authorityRepository.UpdateAsync(authority);
}
DapperContextBuilder的接口
公共接口IDapperContextBuilder
{
IDbConnection CreateConnection();
(string, DynamicParameters) QueryBuilder(object conditions, string query);
}
我嘲笑IDbConnection如下,因为我在这个库中使用Dapper
https://github.com/jmg48/NSubstitute.DbConnection
嘲弄
sql查询和内存数据库作为sql Lite
测验
private readonly IDbConnection _fakedbConnection;
public AppService_Tests()
{
_fakedbConnection = Substitute.For<IDbConnection>().SetupCommands();
}
[Fact]
public async Task Should_UpdateStatus_As_Edit()
{
// Arrange
int id = 1001;
_tenantId = AbpSession.TenantId ?? 0;
_userId = AbpSession.UserId ?? 0;
string query = "SELECT TOP 1 * FROM Authority WHERE Id = @Id AND TenantId = @TenantId AND IsDeleted = 0";
var connectionFactory = Substitute.For<IDapperContextBuilder>();
connectionFactory.CreateConnection().Returns(_fakedbConnection);
UsingDbContext(async context =>
{
CreateAuthorities(context, _tenantId, _userId);
// Simulate Dapper behavior
var item = context.Authority.FirstOrDefault(x=> x.Id == id);
_fakedbConnection.SetupQuery(query).Returns(item);
});
var dto = new AuthorityStatusUpdateInputDto()
{
Id = id,
Status = AuthorityStatus.Edit
};
await _authorityAppService.UpdateStatus(dto);
//Asserts
}
该值从上下文返回为
var item = context.Authority.FirstOrDefault(x=> x.Id == id)
;但是,异常被抛出如下,并且它只是
对于WEB API的单元测试,它运行良好。
例外
System.InvalidOperationException : The instance of entity type 'Authority' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey, Nullable`1 fallbackState)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Attach(TEntity entity)
at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.AttachIfNot(TEntity entity)
at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.Update(TEntity entity)
at Abp.EntityFrameworkCore.Repositories.EfCoreRepositoryBase`3.UpdateAsync(TEntity entity)
at LegalRegTech.MasterData.AuthorityAppService.SetAsDraft(Authority authority, AuthorityStatusUpdateInputDto input) in c:\6clicks\src\LegalRegTech.Application\MasterData\AuthorityAppService.cs:line 967
at LegalRegTech.MasterData.AuthorityAppService.UpdateStatus(AuthorityStatusUpdateInputDto input) in c:\6clicks\src\LegalRegTech.Application\MasterData\AuthorityAppService.cs:line 639
at LegalRegTech.Tests.Authority.AuthorityAppService_Tests.Should_UpdateStatus_As_Edit() in c:\6clicks\test\LegalRegTech.Tests\Authority\AuthorityAppService_Tests.cs:line 1042
--- End of stack trace from previous location ---