@maliming Thanks. You code works. Mock session in TestBaseModule with LifestyleSingleton.
But the next problem is i want different value for each testcase. how to do it ???
var session = Substitute.For<MyAppSession>(
Resolve<IPrincipalAccessor>(),
Resolve<IMultiTenancyConfig>(),
Resolve<ITenantResolver>(),
Resolve<IAmbientScopeProvider<SessionOverride>>()
);
session.LegacyTenantCode.Returns("425599f0-8383-41e6-bcb6-7710f5c29e8b");
LocalIocManager.IocContainer.Register(Component.For<IAppSession>().Instance(session));
//this method will trigger datafilter automatically
var output = await MyAppService.GetProjects(
new GetProjectsInput
{
MaxResultCount = 2,
Sorting = "DesignCode"
});
//Assert
output.TotalCount.ShouldBe(4);
output.Items.Count.ShouldBe(2);
@maliming
I do it now.
my mock code is at testcase's arrange part. but it also call MyAppSession's LegacyTenantCode (i have setted it virtual ) not from NSustitute.
where is the right place for the mock code
For DataFilter, it uses DbContexts GetCurrentTenantCode method. Not using MyAppSession
s GetCurrentTenantCode method.
@maliming
UserClaimsPrincipalFactory.cs (modified)
public override async Task<ClaimsPrincipal> CreateAsync(User user)
{
var claim = await base.CreateAsync(user);
if (user.TenantId.HasValue)
{
//find legacy user
var legacyTenant = await _sysTenantManager.FindById((int)user.TenantId);
if (legacyTenant != null)
{
claim.Identities.First().AddClaim(new Claim(MyClaimTypes.LegacyTenantCode, legacyTenant.TenantCode));
}
}
return claim;
}
@maliming
MyAppSession.cs
public class MyAppSession: ClaimsAbpSession, ITransientDependency, IAppSession
{
public MyAppSession(
IPrincipalAccessor principalAccessor,
IMultiTenancyConfig multiTenancy,
ITenantResolver tenantResolver,
IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider
) :
base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
{
}
public string LegacyTenantCode
{
get
{
var legacyTenantCodeClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == MyClaimTypes.LegacyTenantCode);
var claimValue = legacyTenantCodeClaim?.Value;
return !string.IsNullOrEmpty(claimValue) ? claimValue : null;
}
}
}
MyDbContext
protected virtual bool IsLegacyTenantCodeFilterEnabled =>
CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled(MyDataFilters.MayHaveTenantCode ) == true;
protected virtual string CurrentTenantCode => GetCurrentTenantCode();
private string GetCurrentTenantCode()
{
var legacyTenantCodeClaim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == JungleParkClaimTypes.LegacyTenantCode);
var claimValue = legacyTenantCodeClaim?.Value;
return !string.IsNullOrEmpty(claimValue) ? claimValue : null;
}
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType)
{
if (typeof(IMayHaveLegacyTenantCode).IsAssignableFrom(typeof(TEntity)))
{
return true;
}
return base.ShouldFilterEntity<TEntity>(entityType);
}
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IMayHaveLegacyTenantCode).IsAssignableFrom(typeof(TEntity)))
{
Expression<Func<TEntity, bool>> mayHaveLegacyTenantCodeFilter = e => ((IMayHaveLegacyTenantCode)e).TenantCode == CurrentTenantCode || (((IMayHaveLegacyTenantCode)e).TenantCode == CurrentTenantCode) == IsLegacyTenantCodeFilterEnabled;
expression = expression == null ? mayHaveLegacyTenantCodeFilter : CombineExpressions(expression, mayHaveLegacyTenantCodeFilter);
}
return expression;
}
I add some addtional data to user claims using UserClaimsPrincipalFactory and using the data to do datafilter. the data can accessed through MyCustomAppSession
After this, i will write unit(integrated) test to test some method using datafilter.
My Question:
Thanks.
@maliming
is there any negative effects if i change CreateWithAdminUserAsync ouw TransactionScopeOption.RequiredNew to Required ???
@maliming
I modifyied some code of CreateWithAdminUserAsync
using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiredNew))
changed to
using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.Required))
It need to reuse uow.
It works now thanks.
@maliming it can works if separately run. but i need call aspnetzero`s method of TenanetManager.CreateWithAdminUserAsync. Becasuse some logic inside.