У меня есть приложение С#, в котором я создаю некоторые тесты, используя Moq. Для одной из моих конечных точек пользователь может передать один из нескольких параметров, это используется для построения лямбды, которая запрашивает базу данных:
var existingCriteria = await _criteriaService.GetCriteriaBy(e =>
e.IsActive &&
e.Crop == request.Crop &&
e.Region == request.Region &&
e.Market == request.Market &&
e.ProductStage == request.ProductStage &&
e.Trait == request.Trait &&
e.HarvestType == request.HarvestType
);
Для моего конкретного теста мне важны только 2 параметра, и я использую этот ввод для GetCriteriaBy.
var request = new CriteriaRequest
{
Crop = "Corn",
Region = "NA"
};
var response = await new CriteriaController(_criteriaService.Object).AddCriteria(request);
Затем моя фиктивная служба настроена следующим образом:
Expression<Func<Criteria, bool>> matchExpression = x =>
x.IsActive == true &&
x.Crop == "Corn" &&
x.Region == "NA" &&
x.Market == null &&
x.ProductStage == null &&
x.Trait == null &&
x.HarvestType == null;
mock.Setup(cr => cr.GetCriteriaBy(It.Is<Expression<Func<Criteria, bool>>>(x => Lambda.Equals(x, matchExpression))))
.ReturnsAsync((Expression<Func<Criteria, bool>> where) =>
{
return new List<CriteriaResponse>() {
new CriteriaResponse {
Id = 1,
Crop = "Corn",
Region = "NA"
}
};
});
Но он никогда не ловит мой тестовый пример в Setup
. Если я переключу It.Is
на It.IsAny
, это сработает, но тогда все мои тесты перехватываются этой установкой, и я хочу, чтобы здесь давали ответ только некоторые тесты.
Что я могу сделать, чтобы моя функция настройки работала должным образом?
3 ответа
Все еще ищу лучшее решение, но вот что я использовал, чтобы заставить его работать:
mock.Setup(cr => cr.GetCriteriaBy(It.IsAny<Expression<Func<Criteria, bool>>>()))
.ReturnsAsync((Expression<Func<Criteria, bool>> where) =>
{
var criteria = new List<Criteria>()
{
new Criteria(){
Id = 1,
Crop = "Corn",
Region = "NA"
}
};
IQueryable<Criteria> query = criteria.AsQueryable();
var filtered = query.Where(where);
var response = new List<CriteriaResponse>();
foreach (var item in filtered)
{
response.Add(new CriteriaResponse()
{
Id = item.Id,
Crop = item.Crop,
Region = item.Region
});
}
return response;
});
Кажется, что это слишком много кода для репликации чего-то, что должно работать в Moq.
Я подозреваю, что это происходит из-за несоответствия в лямбда-выражении. Например, IsActive
действительно должно быть true
на основе критериев поиска?
Попробуйте просто:
Expression<Func<Criteria, bool>> matchExpression = x =>
x.Crop == "Corn" &&
x.Region == "NA";
Если вы сузите область действия выражения соответствия, ваши шансы на попадание возрастут.
IsActive == true
был одной из моих попыток настроить ввод, чтобы он соответствовал, но безуспешно. В моем контроллере он сопоставляет request
со всеми полями в лямбде, даже если они пустые. Я предполагаю, что между лямбдами есть некоторая мета-разница, но я не могу ее найти.
Я сомневаюсь, что это то, что вы изначально хотели, но я думаю, что вы можете этого добиться (с немного меньшим количеством кода, чем в ваш собственный ответ), скомпилировав выражение и затем вызвав его с объектом, который подходит для фильтрации.
Что-то вроде:
mock.Setup(cr => cr.GetCriteriaBy(It.IsAny<Expression<Func<Criteria, bool>>>()))
.ReturnsAsync((Expression<Func<Criteria, bool>> expr) =>
{
var isCornMatch = expr.Compile().Invoke(new Criteria { IsActive = true, Crop = "Corn" });
if (isCornMatch)
{
return new List<CriteriaResponse>
{
new CriteriaResponse {
Id = 1,
Crop = "Corn",
Region = "NA"
}
};
}
return new List<CriteriaResponse>();
});
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.
List<CriteriaReponse>
всех тестовых ответов и просто выполнитеWhere(where)
, чтобы определить, что нужно вернуть.where
. Например, он используетCriteria
для запроса, но возвращаетCriteriaResponse
. Если есть способ разобрать запросwhere
, который мог бы работать?Lambda.Equals()
? (я не знаю классLambda
и не могу найти для него никакой документации)