C# 如何用假货来模仿服务?
我有一个简单的实体框架存储库,可以通过服务调用进行访问(请参阅 查看相关课程)。我正在尝试测试服务,如下所示C# 如何用假货来模仿服务?,c#,.net,unit-testing,fakeiteasy,C#,.net,Unit Testing,Fakeiteasy,我有一个简单的实体框架存储库,可以通过服务调用进行访问(请参阅 查看相关课程)。我正在尝试测试服务,如下所示 public class ProductServiceTests { private IProductService sut; private IProductRepository productRepo; [Fact] public async Task CanCallGetProductById() { //Arrange
public class ProductServiceTests
{
private IProductService sut;
private IProductRepository productRepo;
[Fact]
public async Task CanCallGetProductById()
{
//Arrange
productRepo = new Fake<IProductRepository>().FakedObject;
sut = new ProductService(productRepo);
var id = 1;
var expectation = new Product { Id = id };
A.CallTo(() => sut.GetProductById(id)).Returns(expectation);
// Act
var result = await sut.GetProductById(id);
// Assert
Assert.Equal(id, result.Id);
}
}
sut = new Fake<IProductService>().FakedObject;
public class ProductService : IProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public async Task<Product> GetProductById(int id)
{
//throw new NotImplementedException();
return await _productRepository.GetAll()
.FirstOrDefaultAsync(x => x.Id == id);
}
}
然而,这种方法也有问题:对函数wait sut.GetProductById(id)
的调用实际上并不调用任何被测试的代码。事实上,如果我抛出一个异常,测试仍然通过
public async Task<Product> GetProductById(int id)
{
throw new NotImplementedException();
//return await _productRepository.GetAll().FirstOrDefaultAsync(x => x.Id == id);
}
而ProductService
的实现如下
public class ProductServiceTests
{
private IProductService sut;
private IProductRepository productRepo;
[Fact]
public async Task CanCallGetProductById()
{
//Arrange
productRepo = new Fake<IProductRepository>().FakedObject;
sut = new ProductService(productRepo);
var id = 1;
var expectation = new Product { Id = id };
A.CallTo(() => sut.GetProductById(id)).Returns(expectation);
// Act
var result = await sut.GetProductById(id);
// Assert
Assert.Equal(id, result.Id);
}
}
sut = new Fake<IProductService>().FakedObject;
public class ProductService : IProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public async Task<Product> GetProductById(int id)
{
//throw new NotImplementedException();
return await _productRepository.GetAll()
.FirstOrDefaultAsync(x => x.Id == id);
}
}
公共类ProductService:IPProductService
{
私有只读IPProductRepository\u productRepository;
公共产品服务(IPProductRepository productRepository)
{
_productRepository=productRepository;
}
公共异步任务GetProductById(int id)
{
//抛出新的NotImplementedException();
return await\u productRepository.GetAll()
.FirstOrDefaultAsync(x=>x.Id==Id);
}
}
使用赝品(或模拟或其他东西)帮助测试服务的一般方法是模拟被测系统的合作者(在本例中为IPProductService
),并使用真实的被测系统(如果您不使用真实的被测系统,则您的系统不是“被测”)。因此,使用原始代码并进行改编,您可能需要这样的内容:
public class ProductServiceTests
{
private IProductService sut;
private IProductRepository productRepo;
[Fact]
public async Task CanCallGetProductById()
{
//Arrange
productRepo = new Fake<IProductRepository>().FakedObject;
sut = new ProductService(productRepo);
var id = 1;
var expectation = new Product { Id = id };
// This is different from your example.
// The idea is to configure `productRepo`, not `sut`.
// Also, I don't know the interface for `IProductRepository`,
// so you'll have to adjust this call to match `GetAll`
A.CallTo(() => productRepo.GetAll(id)).Returns(new [] {expectation});
// Act
var result = await sut.GetProductById(id);
// Assert
Assert.Equal(id, result.Id);
}
}
公共类ProductServiceTests
{
私人IPS服务sut;
私人iproductrepo;
[事实]
公共异步任务CanCallGetProductById()
{
//安排
productRepo=new Fake().FakedObject;
sut=新产品服务(productRepo);
var-id=1;
var期望=新产品{Id=Id};
//这与您的示例不同。
//其思想是配置'productRepo',而不是'sut'。
//另外,我不知道“IPProductRepository”的接口,
//因此,您必须调整此调用以匹配“GetAll”`
A.CallTo(()=>productRepo.GetAll(id)).Returns(new[]{expectation});
//表演
var result=wait sut.GetProductById(id);
//断言
Assert.Equal(id,result.id);
}
}
非常感谢您的解决方案。不幸的是,我无法根据我的代码修改您的答案(但我想这是因为我的无知)。实际上,我的存储库没有实现GetProductById
方法。它只实现了一个GetAllProducts
方法,`IPProductService`使用该方法通过其id
查找产品。我在新编辑的问题中添加了此信息。我没有说过存储库实现了GetProductById
。我说要配置productRepo.GetAll
。如果您配置GetAll()
,我的方法应该有效,但需要注意的是,您需要让它返回一个实现IDbAsyncQueryProvider
的类,这可能很难实现。我不是EntityFramework用户,因此建议遵循Ben Hall的建议。不过,由于您是新加入FIE的,首先练习测试不使用EF的代码变体可能会有所帮助。再次感谢您的帮助。我会按照你的建议去做,我相信我会解决的。