I am using Test project generated by MVC Asp Net Core (Full Standard) template.
My LocalIocManager has more then 1000 registered components.
This property (LocalIocManager) is defined on AbpIntegratedTestBase
I changed UserAppService and i need some another component that is registered on LocalIocManager.
When i run a unit test like:
```c#
[Fact]
public async Task GetUsers_Test()
{
var _userAppService = Resolve
// Act
var output = await _userAppService.GetAll(new PagedResultRequestDto
{
MaxResultCount = 20,
SkipCount = 0
});
// Assert
output.Data.Count().ShouldBeGreaterThan(0);
}
```
The method "Resolve" call resolve form LocalIocManager and _userAppService is created but IocManager property inside _userAppService is created empty, without registered components.
I need that the IocManager property create inside _userAppService be the same as LocalIocManager with all registered components.
Somebody Helps?
Thanks.
Ok, I understand the reasons, but is there a way, from TestBase, to register a component on internal IocManager? I have some classes like extensions (using static this) that need to resolve object that is only possible using IocManager.Instance.
Show your code.
One more question, can i use Property Injection? it will work like Constructor Injection?
Show your code.
I have many entities that implement IUnidadeNegocioScope and i need to extend IQueryable<> with ByScope method that use AbpSession and UserManager to apply a filter on IQuerable.
```c#
public static IQueryable
where TEntity : class, IEntity
where TUnidadeNegocioFilialScope : IUnidadeNegocioFilialScope
{
using (var abpSession = IocManager.Instance.ResolveAsDisposable
using (var userManager = IocManager.Instance.ResolveAsDisposable
{
var usuarioUnidadesNegocioIds = userManager.Object.Users
.Include(usuario => usuario.UnidadeNegocios)
.Where(usuario => usuario.Id == abpSession.Object.UserId)
.SelectMany(usuario => usuario.UnidadeNegocios.Select(unidadeNegocio => unidadeNegocio.Id))
.ToList();
return GetAll.Where(e => e.UnidadeNegocioScopeId.HasValue && usuarioUnidadesNegocioIds.Contains(e.UnidadeNegocioScopeId.Value));
}
}
```
I have other cases when i need IocManager.Instance but i can solve them if Property Injection work.
I have Abstract Classes that need to inject "Managers" and i dont want to force All subclasses to inject the same interfaces on constructor.
I know that i can use "IAggregateService Pattern" mergin all dependences of a base class on a single interface like a helper, but i would have to refactor too much code, so Property Inject is a good solution if works.
```c#
public abstract class ToolbarIndex
where TCrudPermition : ICrudPermissionMapper
{
// AFTER => using Property Injection if work
public TCrudPermition Permissions { get; set; }
public ViewModelToolbarItemCreate Create { get; set; }
public ViewModelToolbarItemEdit Edit { get; set; }
public ViewModelToolbarItemDelete Delete { get; set; }
public ViewModelToolbarItem Details { get; set; }
protected ToolbarIndex()
{
// BEFORE => using IocManager Instance
// TCrudPermition permissions= IocManager.Instance.Resolve<TCrudPermition>();
Create = new ViewModelToolbarItemCreate(Permissions.Create);
Edit = new ViewModelToolbarItemEdit(Permissions.Update);
Delete = new ViewModelToolbarItemDelete(Permissions.Delete);
Details = new ViewModelToolbarItem();
}
}
```
Yes, this seems to be a good use case of property injection.
I will test using Property Injection and see if it will work.
Thanks for your help!
You can't property inject in an IQueryable though.
Yes, I know that will not work on "IQuerable".
In the case of the extensions, do you know how to get the objects without affecting the unit tests? How to register interfaces from test class in IocManager.Instance?
How and where is ByScope used? It probably shouldn't be an extension method.
It is used within Repository.GetAll() that implement IQueryable.
It define a specific where clause on GetAll().
I think i will change this implementation to use "Query Object Pattern" so i will have a constructor to inject dependence and dont break unit test.
I will check "Specification Pattern" implementation on Abp.
Project Injection doesn't work on Unit Test!!!
Only Constructor Injection.
Someone know how make Property Injection work on Unit Test? using LocalIocManager to resolve objects?
It is used within Repository.GetAll() that implement IQueryable.
Do you mean with Repository.GetAll()?
```c#
var query = _scopeRepository.GetAll().ByScope();
I suggest using [Domain Services](https://aspnetboilerplate.com/Pages/Documents/Domain-Services):
```c#
var query = _scopeManager.GetScopes();
Someone know how make Property Injection work on Unit Test? using LocalIocManager to resolve objects?
Show your code.
I know i can refator this sample and put Manager on construtor, but if Property injection worked, resolve all my problems.
When running project, Property Manager is resolved by IocManager, when i call GetAll() from Unit Test, repository has object and Manager is null.
So, i cant use Property injection because i will has error when implement test.
//Property Injection
public TManager Manager { get; set; }
protected readonly IRepository<TEntity, TPrimaryKey> Repository;
protected BaseApplicationService(
IRepository<TEntity, TPrimaryKey> repository
)
{
//REMOVED because problem with UNIT TEST
//Manager = IocManager.Instance.Resolve<TManager>();
Repository = repository;
}
[UnitOfWork(false)]
public virtual DataSourceResult<TGrid> GetAll(DataSourceRequestFilter<TFilter> request)
{
...
var aggregate = Manager.GetAggregate();
.....
}
public class UserAppService_Tests : AMCTestBase
{
private readonly IUserAppService _userAppService;
public UserAppService_Tests()
{
_userAppService = Resolve<IUserAppService>();
}
[Fact]
public async Task GetUsers_Test()
{
// Act
//var output = await _userAppService.GetAll(new PagedResultRequestDto{MaxResultCount=20, SkipCount=0} );
var output = _userAppService.GetAll(new DataSourceRequestFilter<UserFilter>());
// Assert
output.Data.Count().ShouldBeGreaterThan(0);
}
How is TManager registered?
TManager is IDomainService, is registered by Abp.
I have classes that is passed by Generics that has "new()" constraint and i use "= new T()" to create the instance and use IocManager.Instance to resolve dependence.
So i can't use constructor injection without refactory.
If Property Injection works, i can get instance of class declaring a property and removing use of IocManager.Instance.
the problem occurs only in the test
i use "= new T()" to create the instance and use IocManager.Instance to resolve dependence.
Do you mean register? Show your code.
TKendoComboDto has "new" constraint
and i create an instance using new TKendoComboDto(), but TKendoComboDto implementation can use IocManager.Instance.
[UnitOfWork(false)]
protected async Task<DataSourceResult<TKendoComboDto>> GetAllComboFromAsync<TKendoComboDto>(DataSourceRequest request,
Expression<Func<TEntity, bool>> where)
where TKendoComboDto : IKendoComboDto<TKendoComboDto, TEntity, TPrimaryKey>, new()
{
var query = Manager.GetAll().AsNoTracking();
if (where != null)
query = query.Where(where);
return await query.ToDataSourceComboResultAsync<TKendoComboDto, TEntity, TPrimaryKey>(new TKendoComboDto(), request);
}
How is that relevant?
If i cant use Property Injection with Test.
I will need to refactory a significant amount of code. I am using Property injection on this kind of classes.
I use some class to format data and customize client components and get some business rules like projection, filters and sorts for app services.
Can you provide a repro?
Do you need a sample code to reproduce a problem with Property Injection on Test?
Yes.
I will make a sample using boilerplate template. Only one thing i forgot to say. Im not using InMemory database for test.
I'm using LocalDB because i need to use store procedure and triggers.
Thank you soo much for your help and attention.
A clean fork of aspnetboilerplate/module-zero-core-template would be good.
acjh, thanks for your help!
I've created a template and checked that Property Injection is working !!.
I found the problem in my project, it's dependency on compiled assembly (Module) using "IocManager.Instance".
Now, with property injection, I can move on with my tests! I'll refactor to use Constructor Injection as soon as I find the time