lundi 24 août 2015

How to mock IRepository

I want to mock a unit of work interface with repositories inside for unit test purpose. So far I am able to do it like below.

namespace Liquid.Service.UnitTest
{
    using Liquid.DataAccess.Interface;
    using Liquid.Domain;
    using Domain.Interface;
    using Moq;
    using System.Collections.Generic;
    using System.Linq;

    internal class Helper
    {
        internal IUnitOfWork MockUnitOfWork(ICollection<Dummy> dummies = null,
            ICollection<ProductType> productTypes = null)
        {
            dummies = dummies ?? new List<Dummy>();
            productTypes = productTypes ?? new List<ProductType>();

            var dummyRepositoryMock = MockDummyRepository(dummies);
            var productTypeRepositoryMock = MockProductTypeRepository(productTypes);

            var unitOfWorkMock = new Mock<IUnitOfWork>();
            unitOfWorkMock.Setup(x => x.DummyRepository)
                .Returns(dummyRepositoryMock.Object);
            unitOfWorkMock.Setup(x => x.ProductTypeRepository)
                .Returns(productTypeRepositoryMock.Object);

            return unitOfWorkMock.Object;
        }

        private Mock<IDummyRepository> MockDummyRepository(ICollection<Dummy> dummies)
        {
            var dummyRepositoryMock = new Mock<IDummyRepository>();

            dummyRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
                .Returns((int arg1) => dummies.Where(x => x.Id == arg1).SingleOrDefault());

            dummyRepositoryMock.Setup(x => x.Add(It.IsAny<Dummy>()))
                .Callback((Dummy arg1) => dummies.Add(arg1));

            return dummyRepositoryMock;
        }

        private Mock<IProductTypeRepository> MockProductTypeRepository(ICollection<ProductType> productTypes)
        {
            var productTypeRepositoryMock = new Mock<IProductTypeRepository>();

            productTypeRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
                .Returns((int arg1) => productTypes.SingleOrDefault(x => x.Id == arg1));

            productTypeRepositoryMock.Setup(x => x.Add(It.IsAny<ProductType>()))
                .Callback((ProductType arg1) => productTypes.Add(arg1));

            return productTypeRepositoryMock;
        }
    }
}

You see that I've created two method to mock DummyRepository and ProductTypeRepository but because it has same implementation, I think it is redundant for every repositories I have. Below is the Repositories and IRepository code.

namespace Liquid.DataAccess.Interface
{
    using Liquid.Domain;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;

    public interface IDummyRepository : IRepository<Dummy>
    {
    }

    public interface IProductTypeRepository : IRepository<ProductType>
    {
    }

    public interface IRepository<TEntity> where TEntity : class
    {
        IList<TEntity> GetAll();

        Task<List<TEntity>> GetAllAsync();

        Task<List<TEntity>> GetAllAsync(CancellationToken cancellationToken);

        IList<TEntity> PageAll(int skip, int take);

        Task<List<TEntity>> PageAllAsync(int skip, int take);

        Task<List<TEntity>> PageAllAsync(CancellationToken cancellationToken, int skip, int take);

        TEntity FindById(object id);

        Task<TEntity> FindByIdAsync(object id);

        Task<TEntity> FindByIdAsync(CancellationToken cancellationToken, object id);

        void Add(TEntity entity);

        void Update(TEntity entity);

        void Remove(TEntity entity);
    }
}

How can I use a same method to mock every repositories implementation which inherits IRepository?

UPDATE : The test is just a simple add and check like below.

        [Test]
        public void ProductTypeService_Add()
        {
            // GIVEN
            var productTypeData = new ProductType()
            {
                Id = 1,
                Description = "ProductType1"
            };

            // WHEN
            var unitOfWorkMock = new Helper().MockUnitOfWork();
            var productTypeService = new ProductTypeService(unitOfWorkMock);
            productTypeService.Add(productTypeData);

            // THEN
            Assert.That(productTypeService.FindById(1) != null);
        }

Aucun commentaire:

Enregistrer un commentaire