【问题标题】:Setting property Row to Mocked Microsoft.Office.Interop.Excel.Range with Mock使用 Mock 将属性 Row 设置为 Mocked Microsoft.Office.Interop.Excel.Range
【发布时间】:2013-11-28 12:11:27
【问题描述】:

我想模拟 Microsoft.Office.Interop.Excel.Range 以及之后能够获取属性 Row(范围第一行的索引)。最小起订量 v 4.1.1309.1617 / nunit.framework v 2.6.3.13283 在我的单元测试中,我尝试将模拟的行为设置如下:

var moqRowSelected = new Mock<Range>();
const int row = 1;
moqRowSelected.SetupGet(x => x.Row).Returns(row);
moqSheetBase.SetupProperty(x => x.RowSelected, moqRowSelected.Object);

在被单元测试的代码中,我使用 Range 如下:

var iRow = PlanningSheet.RowSelected.Row;
Range row = sheet.Rows[iRow];

测试运行时,会产生以下异常:

错误:缺少方法'instance int32 [My.Example.Implementation.MyClass] Microsoft.Office.Interop.Excel.Range::get_Row()' 来自类 'Castle.Proxies.RangeProxy'。

我怎样才能成功地实现这个模拟?谁能帮帮我,谢谢。

【问题讨论】:

    标签: c# excel unit-testing nunit moq


    【解决方案1】:

    我认为您已经正确地模拟了 PlanningSheet.RowSelected 引用的对象,因此 iRow 应该是正确的。但是,您没有正确模拟 sheet.Rows

    返回的 Range

    让我们重写测试代码如下

     var iRow = PlanningSheet.RowSelected.Row;
     Range rows = sheet.Rows;
     Range row = rows.get_Range(iRow);
    

    我敢打赌,变量 rows 中包含的模拟不包含 get_Range() 的实现,它是索引属性的方法。

    就我个人而言,由于模拟问题,我避免使用索引属性,请参阅 Mocking indexed property

    所以这里的代码似乎可以在您的情况下启用模拟。请注意,我无权访问 PlanningSheet 的类型,因此我将属性 RowSelected 引用的对象作为方法 CodeUnderTest

    的参数传递
        private Range CodeUnderTest(Range rowSelected, Worksheet worksheet)
        {
            int index = rowSelected.Row;
            var range = worksheet.Rows.get_Range(index);
            return (Range) range;
    
        }
    
        [TestMethod]
        public void MySampleTest()
        {
            var moqRowSelected = new Mock<Range>();
            const int row = 1;
            moqRowSelected.SetupGet(x => x.Row).Returns(row);
    
            var moqRows = new Mock<Range>();
            moqRows.Setup(x => x.get_Range(It.Is<object>( (i) => (int) i==row),It.IsAny<object>())).Returns(moqRowSelected.Object);
    
            var mockWorksheet = new Mock<Worksheet>();
            mockWorksheet.SetupGet(w => w.Rows).Returns(moqRows.Object);
    
            var result = CodeUnderTest(moqRowSelected.Object, mockWorksheet.Object);
            Assert.IsNotNull(result);
        }
    

    最后你会看到你必须在mock中为get_Range方法提供所有参数。这是因为如果您不这样做,它将无法编译。错误很明显表达式树不能包含使用可选参数的调用或调用

    【讨论】:

    • 对于只有版本的C#和.NET中的表达式树的索引器来说,这不是限制吗?如果我没记错的话,我已经成功地使用了someMock.Setup(x =&gt; x[row]).Returns(whatever.Object); 之类的东西。
    • 我找到了问题的根源,是我应该模拟 Excel 属性或方法的任何使用,即使它不在将要测试的方法中。例如:如果我使用这一行 @987654325 @ 在另一种方法中,即使我在将要测试的方法中不需要它,我也应该模拟它。现在,我的问题是模拟 sheet.Names.Add("D_" + deal.Id, "=" + newRow.Address); 我该如何模拟它。
    • 你说的即使它不在将要测试的方法中是什么意思?如果您所指的方法是由您的单元测试执行的,那么您将不得不模拟一些生活在那里的对象......我认为您模拟的困难来自您认为有一个模拟对象的事实。例如,在newRow.Rows.Autofit() 中,您必须模拟方法Autofit() 以在访问由变量newRow 引用的对象的属性Rows 时返回的Range 实例,该对象也是一个模拟对象。总而言之,对于这一行,您至少需要两个模拟。
    猜你喜欢
    • 2016-11-26
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多