如何使Microsoft.Azure.Documents.Client CreateDocumentQuery的Moq Setup生效?
刚遇到过类似的坑,给你列几个最可能的排查方向,一个个核对应该能找到问题:
方法签名完全不匹配
Microsoft.Azure.Documents.Client里的CreateDocumentQuery有N多重载,比如带Uri+FeedOptions的、带Uri+查询字符串+FeedOptions的、带SqlQuerySpec的等等。如果你Setup的重载和实现类里实际调用的重载参数个数/类型不一样,Moq根本不会识别到这个调用。
举个例子:如果你的实现类里调用的是client.CreateDocumentQuery<MyDoc>(collectionUri, "SELECT * FROM c", options),但你Setup的是不带查询字符串的版本,那肯定不会触发。解决办法是把实现类里的调用代码和Setup的签名逐字比对,确保参数类型、数量完全一致。DocumentClient实例没被Mock替换
如果你在实现类里是直接new DocumentClient(...)创建的实例,而不是通过构造函数注入你Mock出来的对象,那Moq的Setup自然不会生效——因为测试时用的是真实的DocumentClient,不是你Mock的那个。
解决办法是给实现类加一个接收IDocumentClient(或你自定义的接口)的构造函数,测试时把Mock的对象传进去:// 实现类代码 public class MyDocumentService { private readonly IDocumentClient _client; // 通过构造函数注入客户端 public MyDocumentService(IDocumentClient client) { _client = client; } // 业务方法里用_client调用CreateDocumentQuery } // 测试代码 var mockClient = new Mock<IDocumentClient>(); var service = new MyDocumentService(mockClient.Object);返回的IQueryable未正确转换
CreateDocumentQuery返回的是IQueryable<T>,如果你Setup时直接返回一个普通List,后续如果业务代码里对这个结果做了Linq操作(比如Where、OrderBy),容易因为类型不匹配导致Moq的匹配逻辑失效。
改成这样试试:var testDocs = new List<MyDocument> { /* 测试数据 */ }; mockClient.Setup(x => x.CreateDocumentQuery<MyDocument>(It.IsAny<Uri>(), It.IsAny<FeedOptions>())) .Returns(testDocs.AsQueryable());自定义接口与原方法签名不一致
你说自己定义了接口和实现类,那要确保接口里的CreateDocumentQuery方法和IDocumentClient里你用到的那个重载完全一致——比如参数类型、默认值、返回类型都不能错。如果接口里的方法少了一个可选参数,或者返回类型写成了IEnumerable<T>而不是IQueryable<T>,那Mock的接口方法和实际调用的DocumentClient方法就不是一回事,Setup自然不会触发。It.IsAny
的类型匹配错误
比如你用It.IsAny<string>()匹配Uri参数,或者用It.IsAny<FeedOptions>()但实际调用时传的参数类型完全不对(比如传了SqlQuerySpec),那肯定匹配不上。仔细核对每个参数的类型,确保It.IsAny<T>的T和实际参数类型一致。
内容的提问来源于stack exchange,提问作者manik

