我有一个MVC应用程序(EF6,SQL Server CE 4),我最近重构了一个UnitOfWork
类和一个服务层(以便我可以利用每个请求一个单独的DbContext
,并成功进行交易)。如何构建单元工作/服务层/存储库,以便它们与DI(Unity)和Moq一起工作用于单元测试
此前,我使用Unity将存储库注入控制器。我的单元测试(对于控制器)很容易设置 - 我只是嘲笑每个存储库,并将它们传递给控制器构造函数。
重构后,我现在使用Unity将服务层(到控制器)和UnitOfWork
(进入服务层)注入。服务层现在通过将UnitOfWork.DbContext
传递给存储库的构造函数来实例化每个存储库。
在我的单元测试中,我试图模拟UnitOfWork
和ServiceLayer(并将模拟的UnitOfWork
对象传递给ServiceLayer的构造函数)。但是,测试失败,说“TestFixtureSetup在ControllerTest失败”。
我认为这是由于我试图通过UnitOfWork
模拟进入ServiceLayer模拟,所以将不胜感激关于如何正确执行此操作的任何指导。
下面的相关代码片段。
的UnitOfWork
public interface IUnitOfWork:IDisposable
{
void Save();
IDSMContext Context { get; }
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IDSMContext _context;
public UnitOfWork()
{
_context = new IDSMContext();
}
public IDSMContext Context
{
get {return _context;}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
服务层
public interface IService
{
// Repositories
IUserRepository Users { get; }
IUserTeamRepository UserTeams { get; }
IPlayerRepository Players { get; }
IGameRepository Games { get; }
IUserTeam_PlayerRepository UserTeamPlayers { get; }
void Save();
}
public class Service: IService, IDisposable
{
private IUnitOfWork _unitOfWork;
private IUserRepository _userRepository;
private IUserTeamRepository _userTeamRepository;
private IPlayerRepository _playerRepository;
private IGameRepository _gameRepository;
private IUserTeam_PlayerRepository _userTeamPlayerRepository;
public Service(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
initialiseRepos();
}
private void initialiseRepos(){
_userRepository = _userRepository ?? new UserRepository(_unitOfWork.Context);
_userTeamRepository = _userTeamRepository ?? new UserTeamRepository(_unitOfWork.Context);
_playerRepository = _playerRepository ?? new PlayerRepository(_unitOfWork.Context);
_gameRepository = _gameRepository ?? new GameRepository(_unitOfWork.Context);
_userTeamPlayerRepository = _userTeamPlayerRepository ?? new UserTeam_PlayerRepository(_unitOfWork.Context);
}
public IUserRepository Users { get { return _userRepository; } }
public IUserTeamRepository UserTeams { get { return _userTeamRepository; } }
public IPlayerRepository Players { get { return _playerRepository; } }
public IGameRepository Games { get { return _gameRepository; } }
public IUserTeam_PlayerRepository UserTeamPlayers { get { return _userTeamPlayerRepository; } }
public void Save()
{
_unitOfWork.Save();
}
统一容器实例设置
Instance.RegisterType<IService, Service>(new PerThreadLifetimeManager())
.RegisterType<IUnitOfWork, UnitOfWork>();
控制器构造
public GameController(IService service)
{
_service = service;
}
测试构造
_mockUnitOfWork = new Mock<IUnitOfWork>();
_mockServiceLayer = new Mock<IService>(_mockUnitOfWork.Object); //this line fails
测试控制器方法
GameController Controller = new GameController(_mockServiceLayer.Object);
我一直在试图理解使用服务层的最佳方式 - 它已经发生在我身上了,我最好将所有的存储库方法移动到服务层中,就像你建议的那样(我刚刚没有得到但是,因为我偶然发现的第一个问题是单元测试不起作用)。与此相关的一个问题是,服务层现在将包含很多和很多方法。你会建议有多个服务层? – jag
我会将相关的方法分组到不同的服务中。例如,您最终可能会使用UserService,TeamService和PlayerService。所以你会有一个由几个服务接口/类组成的_service layer_。您可能已经拥有与Controller类相似的分组 –