适用于EF

时间:2015-07-29 15:41:00

标签: c# unit-testing architecture servicestack funq

作为我自己问题的答案:

在服务堆栈中使用Entity Framework与Generic Repository以及为服务编写Integration \ Unit Tests的最优雅方法是什么?

目前,这就是我的结构:

通用存储库层:

public class GenericRepository<TEntity> where TEntity : class
{
    internal DbContext Context;

    //...

    //CRUD Operations, etc.
}

工作单元层:

public class UnitOfWork : IDisposable
{   
    private readonly DbContext _context;

    public UnitOfWork(DbContext ctx)
    {
        _context = ctx;
    }

    private bool _disposed;

    private GenericRepository<User> _userRepository;

    public GenericRepository<User> UserRepository
    {
        get { return _userRepository ?? (_userRepository = new GenericRepository<User>(_context)); }
    }

    //...
}

业务层:

public class UserBusiness
{

    public UnitOfWork UoW { get; set; }

    public void AddUser(Models.User user)
    {
        //Map from domain model to entity model
        var u = Mapper.Map<Models.User, DAL.Repository.User>(user);

        UoW.UserRepository.Insert(u);
        UoW.Save();
    }
}

API项目:

public class AppHost : AppHostBase
{
    public AppHost() : base("Users Service", typeof(UsersService).Assembly) { }

    //...

    public override void Configure(Funq.Container container)
    {
        //...other configuration

        //UoW registration
        container.Register(c => new UnitOfWork(new DbContext("my-DB-connection"))).ReusedWithin(Funq.ReuseScope.Hierarchy);

        //Business layer class registration
        container.Register<UserBusiness>(c=>new UserBusiness {
            UoW = c.Resolve<UnitOfWork>()
        }).ReuseWithin(Funq.ReuseScope.Hierarchy);
    }
}

public class UsersService : Service
{
    public UserBusiness UB { get; set; }
    public object Post(User u)
    {
        UB.AddUser(u);
        //...               
    }
}

所以说到集成测试,我可以做这样的事情:

声明 _appHost

private ServiceStackHost _appHost;

并像这样配置funq容器:

public override void Configure(Funq.Container container)
{
    //...create mocked context
    var mockedContext = new Mock<IDbContext>();
    mockedContext.Setup(x => x.Set<User>()).Returns(new List<User>
    {
        new User { ID = 1, FirstName = "John", LastName = "Doe" }
    });
    //(or use effort or any other way to create it)

    container.Register(c => new UnitOfWork(mockedContext)).ReusedWithin(Funq.ReuseScope.Hierarchy);
}

照常测试:

[Test]
public void Get_User_By_Id()
{
    //...generate client instance (JsonServiceClient) etc.

    var customer = client.Get(new GetCustomer { Id = 1 });    
    Assert.AreEqual("John", customer.FirstName);
    ///...
}

除了让所有图层都可用于DI和模拟之外,我还创建了IDbContext,IGenericRepository,IUnitOfWork等界面。 我没有把它包含在这里,以便尽可能地保持这个。

但我想知道是否有更好(更优雅的方式)来做。

0 个答案:

没有答案