【发布时间】:2022-01-16 01:46:51
【问题描述】:
我在 SomeRepository 中有一个方法,如下所示:
public async Task<Guid> InsertAsync(TEntity entity)
{
await _context.Set<TEntity>().AddAsync(entity);
await _context.SaveChangesAsync();
return entity.Id;
}
这里的_context变量只是EntityFrameworkCore DbContext具体实现的一个实例。
现在我想测试一些方法,并以下列方式使用此方法:
public async SomeDto SomeMethod(){
var guid = await someRepository.InsertAsync(entity);
//...
//A bit of code that now relies on entire entity object and it's Id, which gets assigned same value as guid variable - this is a consequence of a side effect of InsertAsync, illustrated with this line
var someDto = new SomeDto(entity);
return someDto;
}
由于我使用的是起订量,我可以在测试时模拟如下:
// setup
var guid = Guid.NewGuid();
someRepositoryMock.Setup(s => s.InsertAsync(It.IsAny<Data.Entities.SomeEntity>()))
.Returns<Data.Entities.SomeEntity>((a) =>
{
a.Id = guid;
return Task.Run(() => a.Id); }
);
var someClass = new SomeClass(someRepositoryMock.Object)
//act - this is a method I'd like to unit test
var result = await someClass.SomeMethod();
//assert - here
Assert.Equal(guid, result.Id);
//other asserts on result values here
现在,以这段代码为例,问题是当你有一个想要单元测试的方法时,它依赖于它的所有者依赖的副作用,这真的是个好主意在它的模拟中重新创建依赖项的副作用?
我这样做的理由是,通过模拟这种依赖关系及其所有方法的副作用,我有效地隔离了这种依赖关系的所有方面,这对我正在测试的方法很重要。
但是,我有一种预感,这里有些不对劲。感觉好像相同的功能 - 提到的副作用只是在模拟中重写。在这个例子中,副作用的重现当然非常简单,但是很容易想象一个场景,它可以任意复杂并且更难重现。
理想情况下,所有函数都是纯函数,这个问题就会消失。但事实并非如此。
【问题讨论】:
-
不是您问题的答案,而是随机观察 - 您可以使用
return Task.FromResult(a.Id)代替return Task.FromResult(a.Id)或使用.ReturnsAsync(..)代替.Returns(..),然后直接返回您的值
标签: c# unit-testing .net-core entity-framework-core moq