I'm trying to create unit tests for an Excel VSTO add-in I've created, but I've ran into an incredibly mysterious issue that feels well beyond my experience.
In this case, I have a presenter:
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
}
}
My unit test is to verify that when WorkbookActivate
is called, it performs a specific action, e.g.:
[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
// ...
}
Now, when I run this test, it fails when the event is added (which occurs in the presenter's constructor), throwing the following:
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'.
My understanding, based on this related Stack Overflow post was that what I am performing is a third party callback, and that failed prior to Moq 4.0. I am using Moq 4.2.1402.2112.
So here's the weird part: in that Stack Overflow answer, the Moq bug report is mentioned, which possesses a unit test to test this very concept:
[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);
}
And this test, indeed, passes, which implies that my first test should be valid as it is properly handling the event. But what's even stranger is that the inclusion of this test into my unit test .cs file causes the previously failing test (TestLogicWhenWorkbookActivates
) to pass!
These tests are completely independent. Why is the presence of the second causing the first to pass?