使用通用存储库/UnitOfWork 进行模拟

Mocking with Generic Repository / UnitOfWork

如何从通用存储库和服务中测试插入方法? 我有这个通用存储库:

IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "");

TEntity GetById(object id);

IEnumerable<TEntity> GetAll();

void Insert(TEntity entity);

void Delete(object id);

void Delete(TEntity entityToDelete);

void Update(TEntity entityToUpdate);

本作业单元:

IGenericRepository<Department> DepartmentRepository { get; }

和这项服务

public void Insert(string depName, List<Post> posts = null)
{
    try
    {
        var department = new Department(depName, posts);
        unitOfWork.DepartmentRepository.Insert(department);
        unitOfWork.Save();
    }
    catch (Exception ex)
    {
        ErrorSignal.FromCurrentContext().Raise(ex);
        return;
    }
}

我想用 Rhino.Mock

测试这个服务方法
 var mocks = new MockRepository();
IUnitOfWork unitOfWork = mocks.Stub<IUnitOfWork>();
Department dep = new Department("test");
var id = Guid.NewGuid().ToString();

unitOfWork.Expect(svc => svc.DepartmentRepository.Insert(dep));
unitOfWork.Expect(svc => svc.Save());

DepartmentService depService = new DepartmentService(unitOfWork);
// Act
mocks.ReplayAll();
depService.Insert(dep.Name);
var result = depService.GetAll();

而且我总是出错,有人可以帮助我吗? 错误:

"IUnitOfWork.get_DepartmentRepository(); Expected #1, Actual #2."

有几件事应该做得更好:

  • 可以通过静态 MockRepository.GenerateMock 方法创建模拟实例(您使用的存储库实例是旧的 API)
  • DepartmentRepository 属性 应该被嘲笑为 Insert 将进行调用验证
  • mocks.ReplayAll()不需要
  • 不需要调用 depService.GetAll() - 在您的测试中,您将 插入 数据到 mocks,它不会在任何地方插入任何东西,因此提取 已插入 数据不会产生任何结果

考虑到以上几点,您的测试应该更接近于此:

// Arrange
// 1. Instantiate mocks
var unitOfWork = MockRepository.GenerateMock<IUnitOfWork>();
var repository = MockRepository.GenerateMock<IGenericRepository<Department>>();
// 2. Setup unit of work to return mocked repository
unitOfWork.Stub(uow => uow.DepartmentRepository).Returns(repository);
// 3. Setup expectations - note that we ignore Department argument
repository.Expect(rep => rep.Insert(Arg<Department>.Is.Anything));
unitOfWork.Expect(uow => uow.Save());
var dep = new Department("test");
var depService = new DepartmentService(unitOfWork);

// Act
depService.Insert(dep.Name);

// Assert
repository.VerifyAllExpectations();
unitOfWork.VerifyAllExpectations();

几乎没有什么可以改进的 -- 例如,Insert 调用的参数匹配。我把它留给你。