简体   繁体   English

使用ASP.NET Boilerplate对ID​​omainService进行单元测试

[英]Unit testing for IDomainService with ASP.NET Boilerplate

I am unit testing ABP, but I got error below: 我正在对ABP进行单元测试,但以下错误提示:

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. 如果在上下文上调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。 If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. 如果使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。 Object name: 'XXXDbContext'. 对象名称:“ 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. 另外,我在上面的代码_unitOfWorkManager.Current作为null
Is there any suggestion? 有什么建议吗?

UnitOfWork Attribute UnitOfWork属性

Add [UnitOfWork] attribute and make it a virtual method: 添加[UnitOfWork]属性并使其成为virtual方法:

[UnitOfWork]
public virtual async Task<ProductDto> CreateProduct(CreateProductInput input)
{
    var existing = await _productManager.Products
        .Where(p => p.Name == input.Name)
        .FirstOrDefaultAsync();

    // ...
}
[UnitOfWork]
public virtual async Task<Product> CreateProduct(Product input)
{
    var result = await _ProductRepository.InsertAsync(input);
    await _unitOfWorkManager.Current.SaveChangesAsync();
    return result;
}

See: UnitOfWork Attribute Restrictions 请参阅: UnitOfWork属性限制

You can use UnitOfWork attribute for: 您可以将UnitOfWork属性用于:

  • All public or public virtual methods for classes that are used over an interface (Like an application service used over a service interface). 在接口上使用的类的所有公共公共虚拟方法(例如在服务接口上使用的应用程序服务)。
  • All public virtual methods for self-injected classes (Like MVC Controllers and Web API Controllers ). 用于自注入类的所有公共虚拟方法(如MVC控制器Web API控制器 )。
  • All protected virtual methods. 所有受保护的虚拟方法。

IUnitOfWorkManager IUnitOfWorkManager

You can inject IUnitOfWorkManager to begin a UnitOfWork explicitly: 您可以注入IUnitOfWorkManager来显式启动UnitOfWork

public async Task<Product> CreateProduct(Product input)
{
    using (var uow = _unitOfWorkManager.Begin())
    {
        var result = await _ProductRepository.InsertAsync(input);
        await _unitOfWorkManager.Current.SaveChangesAsync();

        await uow.CompleteAsync();

        return result;
    }
}

My issue is resolved by creating Interface for my appservice and then Resolve this Interface in my test projects. 通过为我的appservice创建接口,然后在测试项目中解决此接口,可以解决我的问题。

Thanks for the suggestion from aaron, but it would be complex to using uniofwork in my every application service. 感谢aaron的建议,但是在我的每个应用程序服务中使用uniofwork会很复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM