We've been trying write unit tests for a worker class written in C#, which mocks out a third party API (COM based) using moq to dynamically create the mock objects. NUnit is our unit testing framework.
This third party component implements a couple of interfaces, but also needs to call back into our worker class using events. Our plan was to simulate the events that this 3rd party component can raise, and test that our worker class operated as expected.
Unfortunately we've run into a problem in that moq seems unable to mock out and raise events that are defined externally. Unfortunately I can't provide the code for the exact 3rd party API we're using, but we've recreated the issue using the MS Word API, and also shown how the tests work when when using a locally defined interface:
using Microsoft.Office.Interop.Word;
using Moq;
using NUnit.Framework;
using SeparateNamespace;
namespace SeparateNamespace
{
public interface LocalInterface_Event
{
event ApplicationEvents4_WindowActivateEventHandler WindowActivate;
}
}
namespace TestInteropInterfaces
{
[TestFixture]
public class Test
{
[Test]
public void InteropExample()
{
// from interop
Mock<ApplicationEvents4_Event> mockApp = new Mock<ApplicationEvents4_Event>();
// identical code from here on...
bool isDelegateCalled = false;
mockApp.Object.WindowActivate += delegate { isDelegateCalled = true; };
mockApp.Raise(x => x.WindowActivate += null, null, null);
Assert.True(isDelegateCalled);
}
[Test]
public void LocalExample()
{
// from local interface
Mock<LocalInterface_Event> mockApp = new Mock<LocalInterface_Event>();
// identical code from here on...
bool isDelegateCalled = false;
mockApp.Object.WindowActivate += delegate { isDelegateCalled = true; };
mockApp.Raise(x => x.WindowActivate += null, null, null);
Assert.True(isDelegateCalled);
}
}
}
Could anyone explain why raising events for the locally defined interface works but not the one imported from the 3rd party API (in this case Word)?
I have a feeling that this is to do with the fact we are talking to a COM object (via the interop assembly) but am not sure how to work around the problem.