Search code examples
c#dbcontextunit-of-workaspnetboilerplateobjectdisposedexception

Unit testing for IDomainService with ASP.NET Boilerplate


I am unit testing ABP, but I got error below:

Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'XXXDbContext'.

Here are my detailed steps:

  1. AppService

    public async Task<ProductDto> CreateProduct(CreateProductInput input)
    {
        var existing = // await _productManager.ProductRepository.FirstOrDefaultAsync(p => p.Name == input.Name);
                          await _productManager.Products.Where(p => p.Name == input.Name).FirstOrDefaultAsync();
        if (existing != null) throw new UserFriendlyException(L("ExistedRepeatedAd"));
    
        var newAdEntity = ObjectMapper.Map<Product>(input);
        // Rest of the code
    }
    
  2. ProductManager

    public class ProductManager : IDomainService
    {
        private readonly IRepository<Product, long> _ProductRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;
    
        public ProductsManager(
            IRepository<Product, long> ProductRepository,
            IUnitOfWorkManager unitOfWorkManager)
        {
            _ProductRepository = ProductRepository;
            _unitOfWorkManager = unitOfWorkManager;
        }
    
        #region Products
    
        public IRepository<Product, long> ProductRepository
        {
            get { return _ProductRepository; }
        }
    
        public IQueryable<Product> Products
        {
            get { return _ProductRepository.GetAll(); }
        }
    
        public async Task<Product> CreateProduct(Product input)
        {
            var result = await _ProductRepository.InsertAsync(input);
            await _unitOfWorkManager.Current.SaveChangesAsync();
            return result;
        }
    
        #endregion
    }
    

It will throw error this line:

await _adManager.Ads.Where(p => p.Name == input.Name).FirstOrDefaultAsync();

But if I use this instead, it will work:

await _adManager.AdRepository.FirstOrDefaultAsync(p => p.Name == input.Name);

In addition, I get _unitOfWorkManager.Current as null in the above code.
Is there any suggestion?


Solution

  • My issue is resolved by creating Interface for my appservice and then Resolve this Interface in my test projects.

    Thanks for the suggestion from aaron, but it would be complex to using uniofwork in my every application service.