如何避免使用dynamic模拟Excel.worksheet时?
我试图用NSubstitute或其他模拟框架和MSTest(Visual Studio 2010)来模拟Excel电子表格。 我不确定是否有比这更好的方法 – 这不适合testing:
这是一个例子(这是所有的原型代码,而不是很干净):
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
到目前为止,这么好:如果GetSetting方法与我的testing在同一个项目中 ,则通过。 但是当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'.
作为参考,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 ""; }
最后有趣的是如果我重新定义我的方法的签名如下:
公共静态stringGetSetting( dynamic表,stringsettingName)
它在VSTO项目中工作。
那么发生了什么事情,做这样的事情的最好方法是什么?
谢谢!
VS2012更新: Moq&Interoptypes:在VS2012中工作,在VS2010中失败?
首先:有些东西已经改变了: 如何避免在模拟Excel.worksheet时使用dynamic模式?
我遇到了同样的问题使用NSubstitute嘲笑Excel对象。 dynamic解决了问题,就像你提到的一样。 但是我想find根本原因。
当您的项目有一个引用Microsoft.Office.Interop.Excel.Extensions.dll
您需要检查是否可见embedded互操作types属性。 如果这意味着你的目标。NET 4.0(我可以从dynamic关键字猜测)。
您可以将testing项目定位到.Net 4.0,但您需要将VSTO Project .Net框架更改回3.5。 那么你可能不得不做一些明确的投射,并完全限定的东西来摆脱这些错误:
C#Office Excel Interop“对象不包含”错误的定义 ,这里有几个例子:
.Net 4.0:
if (tmpsheetName == xlApp.ActiveSheet.Name)
.Net 3.5相当于
Worksheet activeSheet = (Worksheet)xlApp.ActiveSheet; if (tmpsheetName == activeSheet.Name)
另一个例子:
rn.Select();
.Net 4.0
xlApp.Selection.HorizontalAlignment = Constants.xlCenter; xlApp.Selection.Font.Bold = true; xlApp.Selection.Merge();
.Net 3.5相当于
rn.HorizontalAlignment = Constants.xlCenter; rn.Font.Bold = true; rn.Merge();
按照上面的例子继续修复所有.net 3.5 vs 4.0语法错误。 不要忘记删除dynamic
参数types并将其replace为原始的Worksheet
。 最后再次启动testing,它会通过!
鉴于我所经历的与Microsoft.CSharp.DLL在这个线程中的所有悲伤我的意见testing与Mocking框架的VSTO .Net 4.0项目不起作用。
事实certificate,使用任何基于城堡的框架(nsubstitute,ninject等)来嘲讽非常复杂的COM互操作对象(如Excel对象或InDesign对象)并不能提供足够的性能启动。 testing运行时间仍然可以在几秒钟内测量。 (通过数十或数百次的testing,这使得unit testing仍然太慢,不能在TDDtesting原则下运行。)
testingExcel逻辑应该被认为是一个集成testing,因此,对实际的Excel对象运行应该没问题,在这种情况下嘲笑不是很有用。 结果将更有用的testing对实际的对象。
testing到放置在Excel和应用程序之间的抽象层将允许快速testing应用程序逻辑。 在集成testing中testing抽象层到excel应该足以彻底地testing应用程序。