如何设置MS Fakes对象的返回值?OData客户端代码单元测试求助
解决OData V4客户端伪程序集的方法返回值设置问题
我明白你的痛点:用OData V4客户端生成器生成了继承Microsoft.OData.Client.DataServiceContext的System类,没法直接用MS Fakes做单元测试,所以生成了伪程序集,但现在不知道怎么给这些生成的方法设置返回值。下面分场景给你具体方案:
1. 先确认伪程序集的基础配置
首先要确保你的测试项目已经正确引用了伪程序集,并且替换了原Microsoft.OData.Client的真实依赖——也就是说,测试时用的是伪类(比如FakeSystem,命名规则一般是原类名前缀加Fake)而非真实的System类。
2. 针对不同类型的方法设置返回值
生成的OData客户端方法主要分查询类和CRUD操作类,分别处理:
场景1:设置查询方法的返回值
如果是返回DataServiceQuery<T>的查询方法(比如GetSystemsQuery()),你需要先模拟一个DataServiceQuery<T>实例,再让伪类的方法返回它。举个同步查询的例子:
// 准备测试数据 var testSystems = new List<YourSystemEntity> { new YourSystemEntity { Id = 1, Name = "Test System 1" }, new YourSystemEntity { Id = 2, Name = "Test System 2" } }; // 模拟DataServiceQuery<T> var mockQuery = new Mock<DataServiceQuery<YourSystemEntity>>(); mockQuery.Setup(q => q.Execute()).Returns(testSystems.AsQueryable()); // 给伪类的查询方法赋值 var fakeContext = new FakeSystem(new Uri("http://your-odata-endpoint")); fakeContext.GetSystemsQuery = () => mockQuery.Object;
如果是异步查询(比如ExecuteAsync()),只需要把返回值改成Task.FromResult即可:
mockQuery.Setup(q => q.ExecuteAsync()).Returns(Task.FromResult(testSystems.AsQueryable()));
场景2:设置CRUD操作的返回值
对于SaveChanges()这类返回DataServiceResponse的方法,你需要手动构建模拟的响应对象:
// 模拟单个操作的响应 var mockOpResponse = new Mock<OperationResponse>(); mockOpResponse.Setup(r => r.StatusCode).Returns((int)HttpStatusCode.OK); mockOpResponse.Setup(r => r.Error).Returns(null); // 模拟整体的DataServiceResponse var mockDataResponse = new Mock<DataServiceResponse>(); mockDataResponse.Setup(r => r.IsBatchResponse).Returns(false); mockDataResponse.Setup(r => r.ToList()).Returns(new List<OperationResponse> { mockOpResponse.Object }); // 设置伪类的SaveChanges方法 var fakeContext = new FakeSystem(new Uri("http://your-odata-endpoint")); fakeContext.SaveChanges = () => mockDataResponse.Object;
如果是异步版本SaveChangesAsync(),同样用Task.FromResult包裹返回值:
fakeContext.SaveChangesAsync = () => Task.FromResult(mockDataResponse.Object);
3. 关键注意事项
- 如果你的伪程序集是用MS Fakes的Shim机制生成的,语法会有点不同,比如用
ShimSystem.GetSystemsQuery = () => mockQuery.Object这种形式,核心逻辑还是模拟目标对象然后赋值。 - 确保测试类中引用了伪程序集的命名空间,一般是原命名空间加上
.Fakes后缀(比如原命名空间是YourODataNamespace,伪命名空间就是YourODataNamespace.Fakes)。 - 对于复杂的查询参数或者筛选条件,你可以在
Setup中添加更具体的匹配规则,比如Setup(q => q.AddQueryOption("filter", It.IsAny<string>()))来覆盖带参数的查询场景。
最后给你一个完整的异步查询测试示例:
[TestClass] public class SystemContextUnitTests { [TestMethod] public async Task GetSystemsQuery_Async_ReturnsExpectedTestData() { // Arrange var testData = new List<YourSystemEntity> { new YourSystemEntity { Id = 1 } }; var mockQuery = new Mock<DataServiceQuery<YourSystemEntity>>(); mockQuery.Setup(q => q.ExecuteAsync()).Returns(Task.FromResult(testData.AsQueryable())); var fakeContext = new FakeSystem(new Uri("http://localhost/test-odata")); fakeContext.GetSystemsQuery = () => mockQuery.Object; // Act var queryResult = await fakeContext.GetSystemsQuery().ExecuteAsync(); var resultList = queryResult.ToList(); // Assert Assert.AreEqual(1, resultList.Count); Assert.AreEqual(1, resultList[0].Id); } }
内容的提问来源于stack exchange,提问作者kor_
相关产品推荐
相关产品推荐

