我想在内部使用存储库模拟一个工作单元接口以进行单元测试。到目前为止,我能够像下面这样做。
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 Mock<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;
}
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;
}
}
}
你知道我已经创建了两个模拟DummyRepository和ProductTypeRepository的方法,但由于它有相同的实现,我认为它对我拥有的每个存储库都是多余的。 下面是Repositories和IRepository代码。
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);
}
}
如何使用相同的方法来模拟继承IRepository的每个存储库实现?
更新: 测试只是一个简单的添加和检查,如下所示。
[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.Object);
productTypeService.Add(productTypeData);
unitOfWorkMock.Verify(x => x.SaveChanges());
// THEN
Assert.That(productTypeService.FindById(1) != null);
Assert.That(productTypeService.FindById(2) == null);
// WHEN
var productTypeData2 = new ProductType()
{
Id = 2,
Description = "ProductType2"
};
productTypeService.Add(productTypeData2);
// THEN
Assert.That(productTypeService.FindById(2) != null);
}
答案 0 :(得分:1)
我认为你的问题过于复杂,因此也解决了问题。如果您没有为其添加任何值,则不需要各种存储库的接口,如 IDummyRepository 和 IProductRepository 。
您的数据类
public class Dummy
{
public int Id { get; set; }
}
public class ProductType
{
public int Id { get; set; }
}
您的ProductTypeService(我只能假设这一点)
public class ProductTypeService
{
private readonly IUnitOfWork _unitOfWork;
public ProductTypeService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddProductType(ProductType productType)
{
_unitOfWork.ProductTypes.Add(productType);
}
}
您的IUnitOfWork
public interface IUnitOfWork
{
IRepository<Dummy> Dummies { get; set; }
IRepository<ProductType> ProductTypes { get; set; }
}
您的IRepository保持不变,因此我不会将其粘贴到此处!
最后你的单元测试
[TestFixture]
public class Class1
{
private Mock<IUnitOfWork> _unitOfWorkMock;
private Mock<IRepository<Dummy>> _dummyRepositoryMock;
private Mock<IRepository<ProductType>> _productTypeRepositoryMock;
[SetUp]
public void Setup()
{
_unitOfWorkMock = new Mock<IUnitOfWork>();
_dummyRepositoryMock = CreateMock<Dummy>();
_productTypeRepositoryMock = CreateMock<ProductType>();
_unitOfWorkMock.Setup(u => u.Dummies).Returns(_dummyRepositoryMock.Object);
_unitOfWorkMock.Setup(u => u.ProductTypes).Returns(_productTypeRepositoryMock.Object);
}
[Test]
public void product_type_service_should_add_item_to_the_underlying_repository()
{
var productTypeService = new ProductTypeService(_unitOfWorkMock.Object);
var productType = new ProductType {Id = 10};
productTypeService.AddProductType(productType);
_productTypeRepositoryMock.Verify(r => r.Add(It.Is<ProductType>(p => p.Id == productType.Id)), Times.Once());
}
private Mock<IRepository<T>> CreateMock<T>() where T : class
{
var mock = new Mock<IRepository<T>>();
// do more common magic here
return mock;
}
}