gpt4 book ai didi

c# - 如何模拟 IRepository

转载 作者:太空宇宙 更新时间:2023-11-03 21:18:51 26 4
gpt4 key购买 nike

我想模拟一个内部存储库的工作单元接口(interface),用于单元测试目的。到目前为止,我可以像下面那样做。

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 但因为它有相同的实现,我认为它对于我拥有的每个存储库都是多余的。下面是存储库和 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);
}

最佳答案

恕我直言,您正在测试错误的东西;也就是说,您正在测试内存中的集合(List<T>)是否可以存储数据并且可以在集合中找到数据。 这总是会产生 true,因为这是内存中集合的目的

您需要创建集成测试,而不是这样做,它将使用底层存储库的实际实现(例如 Entity Framework ),或者只是测试行为你的服务是这样的:

[Test]
public void ProductTypeService_WhenAddingNewItem_CallsSaveChanges()
{
var unitOfWork = new Mock<IUnitOfWork>();
// setup the properties of the mock here...

var service = new ProductTypeService(unitOfWork);
service.Add(new ProductType { Id = 2, Description = "some product" });

unitOfWork.AssertWasCalled(_ => _.SaveChanges());
}

通过这种方式,您可以测试您的服务是否调用了 SaveChanges()方法;实际上保存数据是存储库的责任,正如我上面所说,测试列表是否可以将数据存储在内存中是没有用的。

关于c# - 如何模拟 IRepository<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32195495/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com