I have an unmanaged DLL
which I'm trying to create a .NET
wrapper library for but am getting different behavior when I try and run a NUnit(v3)
test over it compared to if it is just run from a button click off a WinForm app.
Background: During startup of the DLL I call its Connect()
method, which ultimately causes the DLL to make a TCP connection. When the TCP connection is established I then get notified by wiring up a handler to its "Connected" event.
Once connected I then call other commands on the DLL.
In a simple test Winforms app, I have 1 button which instantiates the "DLL" and then calls the Connect()
method. When the thread completes, the app sits idle for about 2 seconds, and then the "connected" event handler fires as expected. The event does not return anything.
But because the connect()
is an expensive operation, and because my library is destined for a larger application, I created a ConnectAsync()
method in my library and made use of the async and await keywords, and a AutoResetEvent. The ConnectAsync()
method returns an instance of the "instantiated" DLL after it gets notified that the TCP connection is up from the event.
A bit of refactoring to the test WinForms app, and it works as expected.
Next step was to make an integration test using NUnit. However when the ConnectAsync()
method is called from an async test, I can see the TCP connection establish on the remote application, but the event handler never fires. A day's worth of testing, searching and trial and error could not turn up why the ConnectAsync()
works perfect off a simple Winforms button but not from a UnitTest.
Here is the test code
[Test()]
public async Task Test1()
{
var conn = await GetConnection();
//assert some commands on the conn
}
private async Task<TCPConnector> GetConnection()
{
return await Task.Run(() =>
{
var mre = new AutoResetEvent(false);
var ctrl = new TCPConnector();
ctrl.serverName = server;
ctrl.serverPort = serverPort;
ctrl.onConnected += () => { mre.Set(); };
ctrl.Connect();
mre.WaitOne();
return ctrl;
});
}
I know this is not strictly a question, but I'm stumped and looking for ideas to try. Or pointers as to what is different between a button click event and a NUnit test execution.
In case it means something to somebody, the dll I'm calling is an unmanaged ActveX
Update1: If use MSTest it works! So it has something to do with NUnit's startup environment.
Update2: Through investigations in this SO post, I by chance replicated the same behaviour without any unit testing frameworks, but instead via reg free COM. So I'm now thinking it is something to do with how the COM is activated and consumed ?
Resolution
Finally found the answer.
Credit to Chris for his answer on this question. All I had to do was add a <comInterfaceExternalProxyStub />
section to the manifest as outlined, and bingo
UPDATE 4
Ignore the last updates and the resolution. They contain misdirection and false positives, and some lack of understanding of my behalf as I worked through the whole world of COM, Regfree COM, Interop, and COM Events. The problem is still unresolved.
The key issue remains that when the COM is run under the context of a unit test the COM events do not fire. When run in a plain .exe they work just fine