绑定到Excel应用程序事件时MissingMethodException - c#

我正在尝试为已创建的Excel VSTO加载项创建单元测试,但遇到了一个非常神秘的问题,感觉超出了我的经验。

在这种情况下,我有一个主持人:

public class Presenter
{
  private readonly Excel.Application Application;

  public Presenter(Excel.Application Application)
  {
    this.Application = Application;

    Application.WorkbookActivate += Application_WorkbookActivate;
  }

  private void Application_WorkbookActivate(Excel.Workbook Wb)
  {
    // logic to be tested
  }
}

我的单元测试是为了验证调用WorkbookActivate时,它是否执行特定的操作,例如:

[Test]
public void TestLogicWhenWorkbookActivates()
{
  var mockApplication = new Mock<Excel.Application>();

  presenter = new Presenter(mockApplication.Object);

  // Act
  mockApplication.Raise(a => a.WorkbookActivate += null, (Excel.Workbook)null);

  // Assert
  // ...
}

现在,当我运行此测试时,添加事件(在演示者的构造函数中发生)后,它将失败,并引发以下情况:

System.MissingMethodException : Error: Missing method 'instance void [ExcelAddIns.TestControl] Microsoft.Office.Interop.Excel.AppEvents_Event::add_WorkbookActivate(class Microsoft.Office.Interop.Excel.AppEvents_WorkbookActivateEventHandler)' from class 'Castle.Proxies.ApplicationProxy'.

基于this related Stack Overflow post的理解是,我正在执行的是第三方回调,并且在Moq 4.0之前失败了。我正在使用Moq 4.2.1402.2112。

因此,这是一个很奇怪的部分:在Stack Overflow答案中,提到了Moq错误报告,该报告具有用于测试这一概念的单元测试:

[Test]
public void InteropExcelTest()
{
  var mockAppExcel = new Mock<Excel.Application>();

  bool isDelegateCalled = false;

  mockAppExcel.Object.WorkbookActivate += delegate { isDelegateCalled = true; };

  mockAppExcel.Raise(ae => ae.WorkbookActivate += null, (Excel.Workbook)null);

  Assert.True(isDelegateCalled);
}

确实,此测试通过了,这意味着我的第一个测试应该正确有效地处理了事件。但是,甚至更奇怪的是,将此测试包含到我的单元测试.cs文件中会导致先前失败的测试(TestLogicWhenWorkbookActivates)通过!

这些测试是完全独立的。为什么第二个存在导致第一个通过?

参考方案

经过一些额外的研究和实验,我相信我已经解决了我的问题。我不是互操作专家,因此,如果我在此处做出任何错误结论,请随时进行编辑或更正。

我正在处理两个项目:

ExcelAddIns.TestControl
ExcelAddIns.TestControl.Tests

两者都需要VSTO引用(包括Microsoft.Office.Interop.Excel等)。所有VSTO引用都将Embed Interop Types设置为true(我相信这是默认设置)。根据我的阅读(请参阅下面的参考),这是问题的关键,因为它有效地分隔了程序集的嵌入式类型,当我的单元测试引用TestControl项目时导致冲突。

因此,我的解决方案是将两个项目中所有VSTO程序集引用的Embed Interop Types设置为false。这导致单元测试通过而没有第二项测试。

参考文献:

Stack Overflow: Moq & Interop Types: works in VS2012, fails in VS2010?

Stack Overflow: What's the difference setting Embed Interop Types true and false in Visual Studio?

Daniel Cazzulino's Blog: Check your Embed Interop Types flag when doing Visual Studio extensibility work

Microsoft Excel 2010和Python中的受保护视图 - python

这里没有代码示例。刚遇到Microsoft Excel 2010的问题,我在linux上有一个python脚本,可从csv文件中提取数据,将数据推送到excel,然后将该文件作为附件通过电子邮件发送到特定的电子邮件地址。我的问题是我在excel文件中使用公式,并且在它第一次打开时进入“ Protected View”。在单击“启用编辑”后,我的公式才会加载。…

Excel POI:当Excel少于135行时,“我们在…中发现了某些内容的问题” - java

使用POI创建Excel时,我的行为很奇怪。每当我的行数少于〜135时,我将无法打开Excel,但出现以下异常:如果我有更多行,则可以毫无问题地打开Excel。这是代码,我如何创建工作表:val out = new ByteArrayOutputStream() try { wb = createWorkbook() wb.writeToOutputStre…

导出Excel文件时使用的最佳语言 - java

我想编写一个宏程序,该程序从文本文件接收数据,然后以特定方式将其排列在excel文件中。我不知道哪种语言具有处理Excel的最佳功能。我更喜欢Java,我看到有人制作了一个名为JExcelApi的api,但是我不确定它的功能。我希望能够基于特定列中的数据在excel中自动生成图形。这有什么可能吗?我猜想微软的VB或C#会具有这样的高级功能,但是我不确定。谢谢…

C#-验证以字符串的一部分作为参数调用了模拟(MoQ)属性的方法 - c#

我正在使用MoQ和C#来模拟公共属性,并且我想知道是否使用任何以一组特定字符开头的字符串调用了模拟方法之一。因此,例如,虽然我知道这可行:mockLogger.Verify(x => x.Information($"Entering {methodName}"), Times.Once); 我正在尝试以下尝试,以查看是否使用以moc…

Excel.Interop的Worksheet.UsedRange属性中可能存在错误? - c#

仔细阅读以下代码。基本上,调用此函数是为了识别工作表的使用范围,遍历该范围并哈希社会安全号。这是问题所在。如果创建电子表格并填充一个单元格,则该函数不会对该单元格进行哈希处理。但是,如果我填充一个以上,它将起作用。这可能是UsedRange属性中的错误吗?还是我错过了什么?非常感谢。伍迪try { foreach (Excel.Worksheet ws in…