如何在Excel VSTO插件中Mock行?索引访问抛异常求助
问题根源与解决方案
这个RuntimeBinderException的核心原因是:你的Mock代码只实现了双参数索引器([行, 列]格式),但测试里用到了单参数索引器([索引]格式),Moq代理对象找不到对应的绑定实现,导致动态调用失败。
为什么会这样?
Excel的Range是COM互操作类型,它的索引器有多个重载:
- 双参数:
Range[RowIndex, ColumnIndex],用于定位单元格/区域的行和列 - 单参数:
Range[Index],用于按顺序访问集合中的元素(比如Rows[1]取第一行)
你在MergeRanges和MockCells里只设置了双参数的索引器Setup,但测试代码里用了range.Rows[1]、row.Cells[1]这种单参数调用,Moq无法匹配到对应的实现,所以抛出了绑定异常。
修复方案
只需要在两个Mock方法中添加单参数索引器的Setup即可:
1. 修改MergeRanges方法
public static Range MergeRanges(params Range[] ranges) { var range = new Moq.Mock<Range>(); // 保留原有的双参数索引器Setup for (int i = 0; i < ranges.Length; i++) { range.SetupGet(r => r[i + 1, Moq.It.IsAny<Object>()]).Returns(ranges[i]); } // 新增单参数索引器Setup,适配Excel的1-based索引 range.SetupGet(r => r[Moq.It.IsAny<int>()]) .Returns((int index) => ranges[index - 1]); range.SetupGet(r => r.Count).Returns(ranges.Length); range.Setup(r => r.GetEnumerator()).Returns(ranges.GetEnumerator()); return range.Object; }
2. 修改MockCells方法
public static Range MockCells(params Object[] values) { var cells = new Moq.Mock<Range>(); // 保留原有的双参数索引器Setup for (int i = 0; i < values.Length; i++) { var cell = MockCellValue2(values[i]); cells.SetupGet(c => c[i + 1, Moq.It.IsAny<Object>()]).Returns(cell); } // 新增单参数索引器Setup cells.SetupGet(c => c[Moq.It.IsAny<int>()]) .Returns((int index) => MockCellValue2(values[index - 1])); var row = new Moq.Mock<Range>(); row.SetupGet(r => r.Cells).Returns(cells.Object); row.SetupGet(r => r.Count).Returns(values.Length); return row.Object; }
补充说明
Excel的所有COM对象索引都是1-based的,所以在Setup里要把传入的索引(比如1)转换成数组的0-based索引(index-1),这和你之前双参数Setup的逻辑保持一致即可。
修改后,测试里的range.Rows[1].Cells[1]这类单参数索引调用就能正确匹配到Mock实现,不会再抛出绑定异常了。
内容的提问来源于stack exchange,提问作者tomwassing
相关产品推荐
相关产品推荐

