Search code examples
c#entity-frameworkunit-testingnunitrhino-mocks

Mocking with Generic Repository / UnitOfWork


How I can test Insert Method from Generic repo and service? I have this generic repo:

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);

this unit of work:

IGenericRepository<Department> DepartmentRepository { get; }

and this service

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;
    }
}

and I want to test this service method with 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();

And always I got errors, can anybody help me? Error:

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

Solution

  • Few things that should be done better:

    • mock instance can be created via static MockRepository.GenerateMock method (repository instance you are using is old API)
    • DepartmentRepository property should be mocked as Insert call verification will be made
    • mocks.ReplayAll() is not needed
    • call to depService.GetAll() is not needed - in your test you will be inserting data to mocks, which don't insert anything anywhere and as a result extracting inserted data won't yield any results

    Having above points in mind, your test should look closer to this:

    // 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();
    

    Few things can be improved -- for example, argument matching for Insert call. I leave that up to you.