lundi 30 mars 2015

Unit Testing Generic Unit of Work and Repository Pattern framework using Moq

I'm at my wits end. I'm learning how to use the Generic Unit of Work and Repository pattern framework (http://ift.tt/JcIZhn). I've got no problem setting up the controllers, unity, and views... they all work on live data. My issue is unit testing these async repositories.


I've came across numerous posts here in stackoverflow and articles in MSDN with regards to mocking the DataContext using Moq (http://ift.tt/1ILhuoW).


However, upon executing the tests, I seem to be facing a roadblock and I have no idea how to fix this. Please bear with me.


Here is the controller I'm testing:



public class TeamsController : Controller
{
private readonly IUnitOfWorkAsync _uow;
private readonly IRepositoryAsync<Team> _repo;

public TeamsController(IUnitOfWorkAsync uow)
{
_uow = uow;
_repo = _uow.RepositoryAsync<Team>();
}

// GET: Teams
public async Task<ViewResult> Index()
{
return View(await _repo.Queryable().ToListAsync());
}
}


Here is the unit test:



[TestMethod]
public async Task Index_AccessIndexPage_MustPass()
{
// arrange
var data = new List<Team>
{
new Team { Id = 1 }
}.AsQueryable();

Mock<DbSet<Team>> mockSet = data.GenerateMockDBSet<Team>();
var mockContext = new Mock<IDataContextAsync>();
mockContext.As<IDBContext>().Setup(c => c.Teams).Returns(mockSet.Object);

_uow = new UnitOfWork(mockContext.Object);

// act
_controller = new TeamsController(_uow);
var result = await _controller.Index();
var model = (List<Team>)((ViewResult)result).Model;

// assert
Assert.IsNotNull(model);
Assert.AreEqual(model.Count, 2);
}


Here is the utility I got from MSDN:



public static Mock<DbSet<TEnt>> GenerateMockDBSet<TEnt>(this IQueryable<TEnt> data)
where TEnt : Entity
{
var mockSet = new Mock<DbSet<TEnt>>();
mockSet.As<IDbAsyncEnumerable<TEnt>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<TEnt>(data.GetEnumerator()));

mockSet.As<IQueryable<TEnt>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<TEnt>(data.Provider));

mockSet.As<IQueryable<TEnt>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<TEnt>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<TEnt>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<TEnt>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator);

return mockSet;
}


Here is the actual exception from the unit test:



Test method MyMVC.Tests.Controllers.TeamsControllerTest.Index_AccessIndexPage_MustPass threw exception:
System.ArgumentNullException: Value cannot be null.
Parameter name: source
Result StackTrace:
at System.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName)
at System.Data.Entity.QueryableExtensions.ToListAsync[TSource](IQueryable`1 source)


The exception is fired during the actual .Queryable() call because the IRepositoryAsync _repo seems to be throwing a null.


Can anyone help?


Thank you.


Aucun commentaire:

Enregistrer un commentaire