Moq Params TargetParameterCountException: несоответствие счетчика параметров Исключение
Ниже приведен общий интерфейс базового репозитория
public interface IRepository<T>
{
IQueryable<T> AllIncluding(params Expression<Func<T,
object>>[] includeProperties);
}
моя сущность
public class Sdk
{
public Sdk()
{
this.Identifier = Guid.NewGuid().ToString();
}
public virtual ICollection<Resource> AccessibleResources { get; set; }
public string Identifier { get; set; }
}
и следующим является конкретное репо
public interface ISdkRepository : IRepository<Sdk>
{
}
теперь я пытаюсь протестировать контроллер, используя moq
Ниже приведен код, который я пытаюсь проверить
public ActionResult GetResources(string clientId) {
var sdkObject = sdkRepository
.AllIncluding(k => k.AccessibleResources)
.SingleOrDefault(k => k.Identifier == clientId);
if (sdkObject == null)
throw new ApplicationException("Sdk Not Found");
return Json(sdkObject.AccessibleResources.ToList());
}
используя следующий тест
[Test]
public void Can_Get_GetResources()
{
var cid = Guid.NewGuid().ToString();
var mockRepo = new Moq.Mock<ISdkRepository>();
var sdks = new HashSet<Sdk>()
{
new Sdk()
{
Identifier = cid,
AccessibleResources = new HashSet<Resource>()
{
new Resource()
{
Id = Guid.NewGuid(),
Description = "This is sdk"
}
}
}
};
mockRepo.Setup(k => k.
AllIncluding(It.IsAny<Expression<Func<Sdk,object>>[]>()))
.Returns(sdks.AsQueryable);
var sdkCtrl = new SdksController(mockRepo.Object);
var returnedJson=sdkCtrl.GetResources(cid);
returnedJson.ToString();
}
и он бросает:
System.Reflection.TargetParameterCountException: несоответствие счетчика параметров
Не знаю почему?
Ответы
Ответ 1
Я думаю, что у вас есть некоторые ограничения здесь с Moq. Он отлично не обрабатывает параметры выражения, так как он может передаваться выражениям как самим значениям. Мок не знает, какая часть выражения предназначена для разрешения и что является частью подписи.
Кроме того, я не могу вспомнить, насколько хорошо Moq обрабатывает параметры xx [], но вполне возможно, что у вас есть комбинация двух проблем.
Можете ли вы создать класс, который предоставляет набор выражений как свойство? Если это так, возможно, будет возможно изменить подпись AllIncluding и указать Moq для соответствия любому экземпляру этого класса.
Обновление
Во время ответа это было ограничение, но теперь возможно. См. Ответ Александра Литвина
Ответ 2
Хотя есть ответ, отмеченный как принятый, я считаю, что есть способ правильно высмеять ваш репозиторий.
Вместо
mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>()))
.Returns(sdks.AsQueryable);
используйте
mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>()))
.Returns((Expression<Func<Sdk,
object>>[] includeProperties) => sdks.AsQueryable());
Ответ 3
Другим решением для решения этой проблемы является использование .AsQueryable()
вместо .AsQueryable
.
Ответ 4
Для других людей, которые ищут ответ на этот вопрос, решение для меня заключалось в добавлении такого же количества параметров в Setup
, что и в выражении в Returns
.
Например:
Не работает с большим количеством аргументов
mock.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string s) => s.ToLower());
Работа с таким же количеством аргументов в выражении в Returns
, как в Setup
mock.Setup(x => x.DoSomething(It.IsAny<string>()))
.Returns((string s1, string s2) => s1.ToLower());