tom*_*ing 14 c# excel vsto unit-testing moq
我试图在Range一个新的行中放置一个模拟(包含值的单元格)Range.但是当我尝试从中访问特定元素时Range,会抛出异常.
我已经尝试了一切,有没有人知道我在这里做错了什么?
例外
消息:测试方法xxx.MockUtilsTest.MockRowsTest引发异常:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:无法将带有[]的索引应用于类型为"Castle.Proxies.RangeProxy"的表达式
测试
[TestMethod]
public void MockRowsTest()
{
var row1 = MockUtils.MockCells("test_row_1", "test_row_1");
var row2 = MockUtils.MockCells("test_row_2", "test_row_2");
var range = MockUtils.MockRows(row1, row2);
Assert.IsNotNull(range);
Assert.AreEqual(2, range.Count);
Assert.IsNotNull(range.Rows);
Assert.AreEqual(2, range.Rows.Count);
Assert.AreSame(row1, range.Rows[1].Cells[1]); // exception is thrown here
Assert.AreSame(row2, range.Rows[2].Cells[1]);
Assert.AreEqual("test_row_1", range.Rows[1].Cells[1].Value2);
Assert.AreEqual("test_row_2", range.Rows[2].Cells[1].Value2);
}
Run Code Online (Sandbox Code Playgroud)
MockUtils
public static Range MockCellValue2(Object value)
{
var cell = new Moq.Mock<Range>();
cell.Setup(c => c.Value2).Returns(value);
return cell.Object;
}
public static Range MockCells(params Object[] values)
{
var cells = new Moq.Mock<Range>();
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);
}
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;
}
public static Range MockRows(params Range[] rows)
{
var mergedRows = MergeRanges(rows);
var range = new Moq.Mock<Range>();
range.SetupGet(r => r.Count).Returns(rows.Length);
range.SetupGet(r => r.Rows).Returns(() => mergedRows);
range.Setup(r => r.GetEnumerator()).Returns(rows.GetEnumerator());
return range.Object;
}
public static Range MergeRanges(params Range[] ranges)
{
var range = new Moq.Mock<Range>();
for (int i = 0; i < ranges.Length; i++)
{
range.SetupGet(r => r[i + 1, Moq.It.IsAny<Object>()]).Returns(ranges[i]);
}
range.SetupGet(r => r.Count).Returns(ranges.Length);
range.Setup(r => r.GetEnumerator()).Returns(ranges.GetEnumerator());
return range.Object;
}
Run Code Online (Sandbox Code Playgroud)
Old*_*Fox 11
Range返回动态对象的索引器,这是您的问题的根源.
Moq用于Castle Dynamic proxy生成假对象,Castle.Proxies.RangeProxy是您生成的类.由于此对象不是COM对象,因此正在调用C#Runtime绑定程序的处理.运行时绑定程序解析类型并查找索引器方法,但由于生成的类没有它,因此无法解析它.
解决问题的最简单方法是将索引器结果返回到严格的Range局部变量:
然后你的测试将失败因为range.Rows[1]等于row1......
所以将测试代码更改为:
[TestMethod]
public void MockRowsTest()
{
var row1 = MockUtils.MockCells("test_row_1", "test_row_1");
var row2 = MockUtils.MockCells("test_row_2", "test_row_2");
var range = MockUtils.MockRows(row1, row2);
Assert.IsNotNull(range);
Assert.AreEqual(2, range.Count);
Assert.IsNotNull(range.Rows);
Assert.AreEqual(2, range.Rows.Count);
Range x = range.Rows[1];
Range y = range.Rows[2];
var xCell = x.Cells[1];
var yCell = y.Cells[1];
Assert.AreSame(row1, x);
Assert.AreSame(row2, y);
Assert.AreEqual("test_row_1", xCell.Value2);
Assert.AreEqual("test_row_2", yCell.Value2);
}
Run Code Online (Sandbox Code Playgroud)
上述UT将通过测试.IMO你应该打破你的聚合调用"原子OPS(多线)和方法"不是因为它会通过测试,因为它会使你的代码成为一个调试友好的代码.(我把你的代码称为"第11条规则")从编写本文开始,它将被读取至少10次...所以让编译器删除传递局部变量并使它成为一个调试友好的代码..).
在这里,您可以阅读简单而简短的解释,其中包含有关c#中动态工作方式的链接.
在这里,您可以阅读有关Castle Dynamic Proxy的更多信息.
BTW; 你也可以这样做:
Range x = range.Rows[1].Cells;
var str = x[1].Value2;
Run Code Online (Sandbox Code Playgroud)
收到价值
| 归档时间: |
|
| 查看次数: |
309 次 |
| 最近记录: |