Moq Params TargetParameterCountException:参数计数不匹配exception
以下是我的通用基础存储库接口
public interface IRepository { IQueryable AllIncluding(params Expression<Func>[] includeProperties); }
我的实体
public class Sdk { public Sdk() { this.Identifier = Guid.NewGuid().ToString(); } public virtual ICollection AccessibleResources { get; set; } public string Identifier { get; set; } }
以下是具体的回购
public interface ISdkRepository : IRepository { }
现在我正在尝试使用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(); var sdks = new HashSet() { new Sdk() { Identifier = cid, AccessibleResources = new HashSet() { new Resource() { Id = Guid.NewGuid(), Description = "This is sdk" } } } }; mockRepo.Setup(k => k. AllIncluding(It.IsAny<Expression<Func>[]>())) .Returns(sdks.AsQueryable); var sdkCtrl = new SdksController(mockRepo.Object); var returnedJson=sdkCtrl.GetResources(cid); returnedJson.ToString(); }
它扔了:
System.Reflection.TargetParameterCountException:参数计数不匹配
不知道为什么?
我认为你在Moq遇到了一些限制。 它不能很好地处理表达式参数,因为它可以作为值本身传递表达式。 Moq无法知道要解析的表达式的哪个部分以及签名的一部分。
另外,我不记得Moq如何处理params xx [],但你很可能在这里遇到两个问题的组合。
您是否能够创建一个将表达式公开为属性的类? 如果是这样,可以更改AllIncluding的签名并告诉Moq匹配该类的任何实例。
更新
在回答时,这是一个限制,但现在是可能的。 请参阅Oleksandr Lytvyn的回答
虽然有一个标记为已接受的答案,但我相信有一种方法可以正确地模拟您的存储库。
代替
mockRepo.Setup(k => k.AllIncluding(It.IsAny>[]>())) .Returns(sdks.AsQueryable);
请用
mockRepo.Setup(k => k.AllIncluding(It.IsAny>[]>())) .Returns((Expression>[] includeProperties) => sdks.AsQueryable());
解决此问题的另一个解决方案是使用: .AsQueryable()
而不是.AsQueryable
。
对于寻找答案的其他人,我的解决方案是在Setup
添加与Returns
表达式中相同数量的参数。
例如:
不使用不同的参数计数
mock.Setup(x => x.DoSomething(It.IsAny(), It.IsAny ())) .Returns((string s) => s.ToLower());
在Setup
中的Returns
表达式中使用相同数量的args
mock.Setup(x => x.DoSomething(It.IsAny())) .Returns((string s1, string s2) => s1.ToLower());