1

我知道类似的问题已经讨论过好几次了,但我猜我的问题略有不同。我正在试验基于域驱动设计的应用程序架构,使用存储库模式进行数据访问和实体框架基础架构。

我想要完成的是拥有可单元测试的系统,该系统也将具有工作单元的意识。

我喜欢系统中有核心服务来处理应用程序中所有业务逻辑的设计,即您有某种 CustomerService.AddOrder(int customerId, Order order) 而不是 ICustomerRepository.Find(int id)。 Orders.Add(订单订单)。使用这种方法,您可以使用更简单直观的界面。

(当然 CustomerService 依赖于 ICustomerRepository 并且可能也依赖于 IOrderRepository,但它会处理逻辑本身)。

但!这种方法的工作单元问题出现了:

我希望在核心服务中有可控的工作单元,即我需要能够启动一个新的工作单元,完成工作并处理它。

我想出的一种方法是:

public interface IUnitOfWork
{
    ICustomerRepository CustomerRepository { get; set; }

    IOrderRepository OrderRepository { get; set; }
}




public interface IUnitOfWorkFactory
{
    void New(Action<IUnitOfWork> work); // this will let you create and then dispose a new instance of IUnitOfWork implementation
}




public class CustomerService
{
    privateTUowFactory _uow { get; private set; }

    public CustomerService(IUnitOfWorkFactory uowFactory)
    {
        _uow = uowFactory;
    }

    public void AddNewOrder(int id, string newName)
    {
        _uow.New(work =>
            {
                var customer = work.CustomerRepository.Find(id);

                // Do some other required stuff

                work.Commit();
            });
    }
}

之后,您只需为 IUnitOfWorkFactory、IUnitOfWork 和存储库创建实现;在客户端代码中,您只需要依赖 CustomerService,这很容易由 IOC 容器处理。

我喜欢这种方法,因为它有点紧凑、结构良好、逻辑组织和直观,但问题是我不知道如何正确地对服务进行单元测试(例如行为测试)。集成测试很容易,但目前我不关心它们。

任何想法将不胜感激。

非常感谢!

4

2 回答 2

2

您刚才描述的是一种域服务形式。我倾向于不向 UoW 公开我的域代码,但不可否认,这是个人喜好。让域服务控制 UoW 范围会给他们一个他们不应该承担的责任(那时它是一个应用程序服务)。相反,我会让域服务依赖于它需要与之协作的存储库(以及可选的其他服务)(使其足够明确但不会令人困惑)。您似乎正在引入接口以使其可测试/可插入,但此时您并没有从它们中获得太多收益。更好的策略可能不是依赖内存数据库上下文(EF)吗?我相信有一个 nuget 包。这样,您可以在存储库中注入内存 dbcontext(我假设您 d想保留这些)实现。然后,SUT 工厂(创建被测系统的东西,即在这种情况下创建域服务的东西)可以将所有东西连接在一起,允许您使用内存中的 dbcontext 进行控制和断言。或者,您可以创建自己的内存存储库,或使用模拟(但这会很脆弱,而且会很痛苦)。在编写前几个测试时,请注意冗长,并坚持不懈地对其进行重构。不这样做会使这些测试要么编写起来很麻烦,要么成为长期维护的负担。或者,您可以创建自己的内存存储库,或使用模拟(但这会很脆弱,而且会很痛苦)。在编写前几个测试时,请注意冗长,并坚持不懈地对其进行重构。不这样做会使这些测试要么编写起来很麻烦,要么成为长期维护的负担。或者,您可以创建自己的内存存储库,或使用模拟(但这会很脆弱,而且会很痛苦)。在编写前几个测试时,请注意冗长,并坚持不懈地对其进行重构。不这样做会使这些测试要么编写起来很麻烦,要么成为长期维护的负担。

于 2013-05-11T13:27:09.650 回答
1

也许您可以创建一个管理活动 UnitOfWorks 的 UnitOfWorkScope 类:

private CustomerRepository customerRepository;

'...

using (UnitOfWorkScope scope = new UnitOfWorkScope())
{
  customer = customerRepository.GetByID(id);
  customer.BuySomething(price)  
  '...
  scope.complete()
}
End Using
于 2013-05-13T17:09:01.093 回答