如何在Moq Setup中验证GetBrowserByNameQuery的传入字符串参数?
解决Moq中验证GetBrowserByNameQuery参数的问题
方法一:用It.Is<T>匹配参数内部属性
Moq默认按引用判断对象是否相等,不同实例就算参数一致也不会匹配。可以在Setup时,通过It.Is<GetBrowserByNameQuery>检查查询对象的参数值。
如果能修改Query类,先给它加个公开的Name属性(方便测试访问):
public class GetBrowserByNameQuery : IQuery<Browser, Browser?> { private readonly string _name; public GetBrowserByNameQuery(string name) { _name = name; } // 新增公开属性用于测试验证 public string Name => _name; public Browser? Execute(IQueryable<Browser> queryable) { return queryable.SingleOrDefault(x => x.Name == _name); } }
然后Setup时用属性匹配:
context.Setup(x => x.ExecuteQuery(It.Is<GetBrowserByNameQuery>(q => q.Name == command.Name))) .Returns((Browser?)null);
要是不想改原类,用反射访问私有字段也行:
context.Setup(x => x.ExecuteQuery(It.Is<GetBrowserByNameQuery>(q => typeof(GetBrowserByNameQuery).GetField("_name", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) .GetValue(q).ToString() == command.Name))) .Returns((Browser?)null);
方法二:重写Query类的相等判断方法
让GetBrowserByNameQuery基于_name的值判断相等,这样Moq就能识别参数相同的不同实例:
public class GetBrowserByNameQuery : IQuery<Browser, Browser?> { private readonly string _name; public GetBrowserByNameQuery(string name) { _name = name; } public Browser? Execute(IQueryable<Browser> queryable) { return queryable.SingleOrDefault(x => x.Name == _name); } public override bool Equals(object? obj) { return obj is GetBrowserByNameQuery query && _name == query._name; } public override int GetHashCode() { return HashCode.Combine(_name); } }
之后你原来的Setup代码直接传实例就能生效:
context.Setup(x => x.ExecuteQuery(new GetBrowserByNameQuery(command.Name))) .Returns((Browser?)null);
方法三:用回调验证参数
如果只是要确认参数符合预期,而非针对性设置返回值,也可以用Callback检查:
context.Setup(x => x.ExecuteQuery(It.IsAny<GetBrowserByNameQuery>())) .Callback<GetBrowserByNameQuery>(q => { // 这里断言参数是否符合预期,假设已经有公开的Name属性 Assert.Equal(command.Name, q.Name); }) .Returns((Browser?)null);
内容的提问来源于stack exchange,提问作者Fcbkevin
相关产品推荐
相关产品推荐

