[英]Expression<Func<T, bool>> is not working as expected in mock setup
這是我要測試的方法:
public async Task<List<Lesson>> GetProfessionalLessonsByTutorIdAsync(long tutorId)
{
return await _unitOfWork.Repository<Lesson>().GetEntities(l => l.TeacherId == tutorId && l.LessonTypeId == 1)
.AsNoTracking().ToListAsync();
}
這里的GetEntities
方法如下:
public IQueryable<TEntity> GetEntities(Expression<Func<TEntity, bool>> condition = null,
Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include = null)
{
IQueryable<TEntity> query = _dbSet;
if (condition != null)
{
query = query.Where(condition);
}
if (include != null)
{
query = include(query);
}
return query;
}
我的測試方法:
[Fact]
public async Task GetProfessionalLessonsByTutorIdAsync_WithTutorIdInputParam_ReturnsListOfLesson()
{
// Arrange
private readonly Mock<IUnitOfWork> _mockUnitOfWork = new Mock<IUnitOfWork>();
private readonly Mock<IHttpContextAccessor> _mockContextAccessor = new Mock<IHttpContextAccessor>();
private readonly Mock<IUserService> _mockUserService = new Mock<IUserService>();
var fakeLessonList = new List<Lesson>
{
new Lesson() { LessonId = 1, LessonTypeId = 1,LanguageId = 1, TeacherId = 1, LessonName = "Professional Lesson"},
new Lesson() { LessonId = 2,LessonTypeId = 2, LanguageId = 2, TeacherId = 2, LessonName = "Professional Lesson"}
}.AsQueryable().BuildMock();
_mockUnitOfWork.Setup(uow => uow.Repository<Lesson>().GetEntities(It.IsAny<Expression<Func<Lesson, bool>>>() ,
It.IsAny<Func<IQueryable<Lesson>, IIncludableQueryable<Lesson, object>>>())).Returns(fakeLessonList.Object);
LessonService lessonService = new LessonService(_mockUnitOfWork.Object, _mockContextAccessor.Object, _mockUserService.Object);
// Act
var exceptedValue = 1;
List<Lesson> lessons = await lessonService .GetProfessionalLessonsByTutorIdAsync(1);
var actualValue = lessons.Count; // Here count should be 1 but its getting 2
//Assert
Assert.Equal(exceptedValue, actualValue);
}
問題是當await lessonService.GetProfessionalLessonsByTutorIdAsync(1);
在測試方法中調用它返回 2 個項目,實際上它應該返回 1 與匹配的條件。
我猜問題出在以下模擬設置代碼中:
_mockUnitOfWork.Setup(uow => uow.Repository<Lesson>().GetEntities(It.IsAny<Expression<Func<Lesson, bool>>>() ,
It.IsAny<Func<IQueryable<Lesson>, IIncludableQueryable<Lesson, object>>>())).Returns(fakeLessonList.Object);
可能是我錯過了什么! 請高手幫忙解答!
注意:如果我按如下方式修改原始方法,則它可以工作。
public async Task<List<Lesson>> GetProfessionalLessonsByTutorIdAsync(long tutorId)
{
return await _unitOfWork.Repository<Lesson>().GetEntities().Where(l => l.TeacherId == tutorId && l.LessonTypeId == 1)
.AsNoTracking().ToListAsync();
}
現在另一個問題是為什么測試方法適用於GetEntities().Where(l => l.TeacherId == tutorId && l.LessonTypeId == 1)
但不適用於.GetEntities(l => l.TeacherId == tutorId && l.LessonTypeId == 1)
。
您設置的問題在於您將GetEntities
設置為始終返回完整的fakeLessonList
列表。 您永遠不會遇到作為參數提供的查詢。
為此,您可以使用 Moq Returns()
方法的另一個重載,該方法提供調用者通過 lambda 方法傳遞的參數。 此外,如果您想根據給定條件實際過濾掉列表,即實際運行查詢,則無需模擬列表。
var fakeLessonList = new List<Lesson>
{
new Lesson() { LessonId = 1, LessonTypeId = 1,LanguageId = 1, TeacherId = 1, LessonName = "Professional Lesson"},
new Lesson() { LessonId = 2,LessonTypeId = 2, LanguageId = 2, TeacherId = 2, LessonName = "Professional Lesson"}
}.AsQueryable(); // .BuildMock(); - no mock, just a real list
_mockUnitOfWork.Setup(uow => uow.Repository<Lesson>().GetEntities(It.IsAny<Expression<Func<Lesson, bool>>>(),
It.IsAny<Func<IQueryable<Lesson>, IIncludableQueryable<Lesson, object>>>()))
.Returns(
(Expression<Func<Lesson, bool>> condition,
Func<IQueryable<Lesson>, IIncludableQueryable<Lesson, object>> include) =>
// Run the queries against the list
// Need to add some checks in case any of those are null
fakeLessonList.Where(condition)
);
我沒有測試代碼,但我希望它能讓您了解需要調整的內容。
編輯:這是您的測試中發生的事情。
GetEntities()
模擬和其他一些...await lessonService .GetProfessionalLessonsByTutorIdAsync(1);
方法。GetEntities(condition)
模擬的調用,但它只是忽略了condition
因為你的模擬(你設置它的方式)不評估任何條件,它總是返回完整列表。 換句話說,無論您的GetProfessionalLessonsByTutorIdAsync
方法是調用GetEntities(condition)
還是GetEntities()
沒有區別,因為模擬設置為始終返回完整列表並忽略傳遞給它的任何條件。
如果您更改GetProfessionalLessonsByTutorIdAsync
的代碼以運行GetEntities().Where(condition)
那么您最終將根據GetEntities()
返回的列表評估condition
。 這樣做的問題是您不再能夠控制condition
發生的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.