Is there a better way to initialize a mocked repository using generics?
I am trying to find a generic way of initializing a mock repository for my test class. As I have multiple repositories I tried doing it using generics. I have a generic repository interface:
public interface IRepository<T> where T: class
{
IQueryable<T> GetAll();
}
My static initialization method looks like this:
public static Mock<T> GetRepository<T, TK>(params TK[] items) where T: class, IRepository<TK> where TK: class
{
Mock<T> mock = new Mock<T>();
mock.Setup(m => m.GetAll()).Returns(items.ToList().AsQueryable);
return mock;
}
To initialize my repository in code I use:
Mock<IRepository<Link>> linkRepository = UnitTestHelpers.GetRepository<IRepository<Link>, Link>(new[] {
new Link { LinkId = 1, Title = "Title 1", Created = DateTime.Now, Url = "http://google.com" },
new Link { LinkId = 1, Title = "Title 2", Created = DateTime.Now, Url = "http://google.com" },
new Link { LinkId = 1, Title = "Title 3", Created = DateTime.Now, Url = "http://google.com" }
});
I feel this is not the most elegant way开发者_运维知识库 of doing this as I have to specify Link twice in the GetRepository method. Is there a nicer/cleaner way of doing this?
Yes, there is a somewhat smoother way to achieve this. As you mention the Link
type parameter is redundant, this is because there is no real need to parametrize the generic IRepository<T>
type. Try this
public static Mock<IRepository<T>> GetRepository<T>(params T[] items) where T: class {
Mock<IRepository<T>> mock = new Mock<IRepository<T>>();
mock.Setup(m => m.GetAll()).Returns(items.ToList().AsQueryable);
return mock;
}
Some unrelated hints:
- Drop the
ToList()
call unless really needed. Adds lazyness and improved readability. - Use a specific
DateTime
rather thanDateTime.Now
to create a repeatable unit-test.
精彩评论