c# - 模拟 Excel.worksheet 时如何避免使用动态?

标签 c# excel mocking vsto nsubstitute

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

这是一个例子(现在都是原型(prototype)代码,不是很干净):

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 方法与我的测试在同一项目中,则此操作通过。但是,当 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 "";
}

最后一个有趣的部分是如果我重新定义我的方法的签名如下:
public static string GetSetting(dynamic sheet, string settingName)
它适用于 VSTO 项目。

那么这是怎么回事,执行此类操作的最佳方法是什么?

谢谢!

最佳答案

VS2012 更新: Moq & Interop Types: works in VS2012, fails in VS2010?

首先:有些事情发生了变化: How do I avoid using dynamic when mocking an Excel.worksheet?

我在使用 NSubstitute 模拟 Excel 对象时遇到了同样的问题。就像你提到的那样,动态解决了这个问题。但是我想找到根本原因。


当您的项目引用 Microsoft.Office.Interop.Excel.Extensions.dll 时,您需要检查 Embed Interop Types 属性是否可见。如果是,则意味着您的目标是 .Net 4.0(我可以从 dynamic 关键字中猜到)。

You can leave the Test Project targeting .Net 4.0 but you need to you change the VSTO Project .Net framework back to 3.5. Then you'll probably have to do some explicit casting and fully qualify things to get rid of these errors:

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

.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 与 4.0 语法错误。不要忘记删除 dynamic 参数类型并将其替换为原始 Worksheet。最后再次启动测试,它会通过!!!

考虑到我在这个 thread 中对 Microsoft.CSharp.DLL 的所有悲痛我认为使用模拟框架测试 VSTO .Net 4.0 项目不起作用。

关于c# - 模拟 Excel.worksheet 时如何避免使用动态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10843188/

相关文章:

java - Junit Mockito NullPointerException for Mock 用于基于构造函数的 Autowiring

excel - 使用工作表名称动态填充列

web-services - 为 Web 服务模拟 Http-503

c# - ElasticSearch C# 客户端 (NEST) : access nested aggregation with Spaces

c# - 封装 Action<T> 和 Func<T>?

c# - 当名称重复时,在 Excel 工作簿中按字符串获取命名范围

excel - '100 4': "排序引用无效。”

php - 如何使用 mockbin API 正确创建一个 bin?

c# - ASP.NET Core Identity session 过期早于配置发生的时间

c# - 在 C# 中运行 Java 代码