在模拟Excel.worksheet时如何避免使用动态?

ton*_*722 10 c# excel vsto mocking nsubstitute

我正在尝试使用NSubstitute或其他模拟框架和MSTest(Visual Studio 2010)来模拟Excel电子表格.我不确定是否有比这更好的方法 - 这对测试来说不太合适:

这是一个例子(这是现在的所有原型代码,并不是很干净):

int[] lowerBounds = { 1, 1 };
int[] lengths = { 2, 2 };

//Initialize a 1-based array like Excel does:
object[,] values = (object[,])Array.CreateInstance(typeof(object), lengths, lowerBounds);
values[1,1] = "hello";
values[2,1] = "world";      

//Mock the UsedRange.Value2 property
sheet.UsedRange.Value2.Returns(values); 

//Test:   
GetSetting(sheet, "hello").Should().Be("world");  //FluentAssertions
Run Code Online (Sandbox Code Playgroud)

到目前为止,非常好:如果GetSetting方法与我的测试在同一个项目中,则会通过.但是,当GetSetting在我的VSTO Excel-Addin项目中时,它会在GetSetting函数的第一行失败并出现以下错误:

System.MissingMethodException: Error: Missing method 'instance object [MyExcel.AddIn] Microsoft.Office.Interop.Excel.Range::get_Value2()' from class 'Castle.Proxies.RangeProxy'.
Run Code Online (Sandbox Code Playgroud)

作为参考,GetSetting从工作表中的columnA获取一个值,并返回columnB中的值.

public static string GetSetting(Excel.Worksheet sheet, string settingName) {
  object[,] value = sheet.UsedRange.Value2 as object[,];
  for (int row = 1; row <= value.GetLength(1); row++) {
    if (value[1, row].ToString() == settingName)
      return value[2, row].ToString();
  }
  return "";
}
Run Code Online (Sandbox Code Playgroud)

最后一个有趣的部分是如果我重新定义我的方法的签名如下:
公共静态字符串GetSetting(动态表,字符串settingName)
它在VSTO项目中工作.

那么是怎么回事,做这样的事情最好的方法是什么?

谢谢!

Jer*_*son 5

VS2012更新: Moq和Interop类型:在VS2012中工作,在VS2010中失败?

首先:发生了一些变化: 在模拟Excel.worksheet时如何避免使用dynamic?

我遇到了使用NSubstitute模拟Excel对象的相同问题。正如您提到的,动态解决了该问题。但是,我想找到根本原因。


当您的项目具有引用时,Microsoft.Office.Interop.Excel.Extensions.dll您需要检查“嵌入互操作类型”属性是否可见。如果是这样,则意味着您的目标是.Net 4.0(我可以从dynamic关键字中猜到)。

您可以保留面向.Net 4.0的测试项目,但需要将VSTO Project .Net框架更改回3.5。然后,您可能必须做一些明确的转换并完全限定条件才能摆脱这些错误:

C#Office Excel Interop“对象不包含”的定义错误,这里有几个示例:

.Net 4.0:

if (tmpsheetName == xlApp.ActiveSheet.Name)
Run Code Online (Sandbox Code Playgroud)

.NET 3.5等效

Worksheet activeSheet = (Worksheet)xlApp.ActiveSheet;
if (tmpsheetName == activeSheet.Name)
Run Code Online (Sandbox Code Playgroud)

另一个例子:

rn.Select();
Run Code Online (Sandbox Code Playgroud)

.Net 4.0

xlApp.Selection.HorizontalAlignment = Constants.xlCenter; 
xlApp.Selection.Font.Bold = true;
xlApp.Selection.Merge();
Run Code Online (Sandbox Code Playgroud)

.NET 3.5等效

rn.HorizontalAlignment = Constants.xlCenter;
rn.Font.Bold = true;
rn.Merge();
Run Code Online (Sandbox Code Playgroud)

按照上述示例,修复所有.Net 3.5 vs 4.0语法错误。不要忘记删除dynamic参数类型并将其替换为原始类型Worksheet。最后再次启动测试,它将通过!!!

考虑到我在该线程中使用Microsoft.CSharp.DLL遇到的所有麻烦,我认为使用Mocking Frameworks测试VSTO .Net 4.0项目无效。